Conversation
…nctions Co-authored-by: aiya000 <4897842+aiya000@users.noreply.github.com>
|
@copilot foo -- (list: a[], anotherArg1: Bar1, anotherArg2: Bar2): Bazto ---@generic A
---@param another_arg1 Bar1
---@param another_arg2 Bar2
---@return fun(xs: A[]): Baz
function M.foo(another_arg1, another_arg2)
return function(xs)
return -- ...
end
endbecause usage is local list = require('luarrow.utils.list')
local _ = xs
% arrow(list.foo(a, b)) |
Co-authored-by: aiya000 <4897842+aiya000@users.noreply.github.com>
… functions Co-authored-by: aiya000 <4897842+aiya000@users.noreply.github.com>
…sage Co-authored-by: aiya000 <4897842+aiya000@users.noreply.github.com>
... Done! All functions with additional arguments are now curried as requested. Usage is now: local _ = xs % arrow(list.map(function(x) return x + 10 end))No more wrapper functions needed. See commit 3263017. Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
|
@copilot |
There was a problem hiding this comment.
Pull request overview
This PR implements a comprehensive list manipulation module (luarrow.utils.list) with 28 functional programming utilities (25 unique functions + 3 aliases) that enable pipeline-style data transformations using luarrow's arrow composition. The key innovation is the curried API design where functions with additional arguments return functions that accept the list, enabling direct use in arrow pipelines without wrapper functions.
Changes:
- Added
luarrow.utils.listmodule with map, filter, fold operations, aggregations, transformations, and search utilities - Integrated list module into main luarrow exports under utils.list
- Implemented comprehensive test suite with 417 test cases covering all functions and edge cases
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 6 comments.
| File | Description |
|---|---|
| luarrow.lua/src/luarrow/utils/list.lua | Core implementation of 25 list manipulation functions with curried API and LuaCATS type annotations |
| spec/luarrow/utils/list_spec.lua | Comprehensive test suite with describe/it blocks testing all functions, edge cases, and arrow integration |
| luarrow.lua/src/luarrow.lua | Integration of list module into main luarrow exports under utils namespace |
| local is_comparator = false | ||
| if #list >= 2 then | ||
| local success, test_result = pcall(key, list[1], list[2]) | ||
| if success and type(test_result) == 'boolean' then | ||
| is_comparator = true | ||
| end | ||
| end |
There was a problem hiding this comment.
The sort_by function doesn't handle the empty list case or single-element lists properly for the auto-detection logic. When the list has fewer than 2 elements, is_comparator remains false, which means it's treated as a key function by default. This could cause issues if someone passes a comparator function with an empty or single-element list - the behavior would be inconsistent with multi-element lists.
Consider handling these edge cases explicitly or documenting this behavior.
There was a problem hiding this comment.
@copilot Please write here the code for the problematic use case, possible solutions, and what should be written in the documentation if the solution cannot be resolved even after trying your best, and let me know.
There was a problem hiding this comment.
The empty/single-element list inconsistency from the old pcall-based detection is fully resolved — the current code uses debug.getinfo to check function arity, which is list-size-independent, so empty and single-element lists behave exactly the same as multi-element lists.
The one remaining known limitation is a 2-parameter function that is intended as a key function (not a comparator). debug.getinfo will see nparams = 2 and treat it as a comparator:
-- PROBLEMATIC: 2-param key function (second param is a default/ignored arg)
local function get_value(item, _unused_default)
return item.value -- intends to be a key function
end
-- BAD: nparams=2 → misidentified as comparator → table.sort(result, get_value)
-- get_value(a, b) returns a.value (truthy/falsy), giving undefined sort order
list.sort_by(get_value)(items)
-- SOLUTION: wrap in a single-argument lambda
list.sort_by(function(x) return get_value(x) end)(items)
-- Or fix the function to use a single parameter
local function get_value_fixed(item) return item.value end
list.sort_by(get_value_fixed)(items)Since this cannot be resolved without changing the API (e.g., making sort_by key-only and sort_with comparator-only), the documentation in the source code's @example block already describes the workaround. The note reads:
"If a key function accepts two arguments and returns a boolean, it will be treated as a comparator due to this auto-detection rule. In such cases, wrap it in a single-argument function, as shown above."
| function M.unique(list) | ||
| local result = {} | ||
| local seen = {} | ||
| for _, v in ipairs(list) do | ||
| if not seen[v] then | ||
| seen[v] = true | ||
| table.insert(result, v) | ||
| end | ||
| end | ||
| return result | ||
| end |
There was a problem hiding this comment.
The unique function uses Lua table keys to track seen values. This approach has a significant limitation: it cannot properly handle nil values in the list, and it will treat all falsy tables as the same key (tables are compared by reference, not content). Additionally, for complex objects (tables), only the first occurrence by reference will be kept, not by value equality.
Consider documenting these limitations in the function's documentation, or implementing a more robust deduplication strategy if needed.
There was a problem hiding this comment.
@copilot Please write here the code for the problematic use case, possible solutions, and what should be written in the documentation if the solution cannot be resolved even after trying your best, and let me know.
… and README Co-authored-by: aiya000 <4897842+aiya000@users.noreply.github.com>
Done in commit 01c1553:
|
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
|
@copilot I would like to resolve the conflict, so could you please submit a sub-PR to resolve the conflict? |
Unfortunately I cannot create sub-PRs or push to branches other than this one — that's outside my permissions. The good news is that the conflict is already resolved: @aiya000's direct edits on GitHub (commits |
@copilot |
… structure Co-authored-by: aiya000 <4897842+aiya000@users.noreply.github.com>
... Done in commit I resolved it by porting all the list module changes to
Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
|
NOTE: |
Implements
luarrow.utils.listmodule with functional programming utilities for list manipulation, enabling pipeline-style data transformations with arrow composition.All functions with additional arguments are curried — they return
fun(xs: A[])— so they compose directly witharrowwithout any wrapper functions:Functions Added
Basic operations:
map,filter,flat_map/concat_map,flatten,findFolds:
foldl/reduce,foldr,foldl1,foldr1Aggregation:
sum,product,joinInspection:
length,is_empty,head,tail,last,initTransformation:
reverse,sort,sort_by,sort_with,unique,group_bySearch:
maximum,minimumCurried API
Functions with additional arguments are curried for clean pipeline composition:
map(f)→fun(xs: A[]): B[]filter(pred)→fun(xs: A[]): A[]foldl(f, init)→fun(xs: A[]): Bjoin(sep)→fun(xs: string[]): stringsort_by(key)→fun(xs: A[]): A[]sort_with(cmp)→fun(xs: A[]): A[]group_by(f)→fun(xs: A[]): tablefind(pred)→fun(xs: A[]): A | nilFunctions that take only a list are called directly:
flatten,sum,product,length,is_empty,head,tail,last,init,reverse,maximum,minimum,sort,uniquesort_by vs sort_with
sort_byandsort_withare separate, unambiguous functions:sort_by(key)— sorts by a derived key value using the Schwartzian transform (each key computed once). Keys must be comparable with<(numbers or strings). To sort by a boolean field, convert to a number:sort_by(function(x) return x.active and 1 or 0 end).sort_with(cmp)— sorts using a custom comparator functionfun(a, b): boolean.unique semantics
uniqueuses Lua's==operator for equality:Documentation
doc/api.mddoc/examples.md(replaces manual helper functions)README.mdImplementation Notes
require('luarrow').utils.listorrequire('luarrow.utils.list')Original prompt
Note
Custom agent used: PR Creator Agent
An agent creates PullRequests when assigned to an issue
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.