array-mumu
A MuMu/Lava plugin to provide fast, typed & heterogeneous array utilities with friendly currying, data-last ergonomics, and keyed-object helpers.
Repository: https://gitlab.com/tofo/mumu-array
License: MIT OR Apache-2.0
Engine compatibility: core-mumu = 0.9.0-rc.4 (host and wasm builds)
What this plugin aims to do
- to expose a comprehensive set of
array:*functions to MuMu/Lava - to enable placeholder-driven partial application (
_) and data-last calling styles - to interoperate cleanly with MuMu values (typed arrays, mixed arrays, keyed arrays/objects, iterators)
- to return predictable, typed results (int/float/string/bool arrays when homogeneous;
MixedArrayotherwise) - to remain wasm-friendly while exporting a host entrypoint for dynamic loading
The plugin registers all symbols via register_all(interp). On native builds it also exports a dynamic entrypoint Cargo_lock(...) so extend("array") can load it at runtime.
Feature overview
1) Query & selection
array:length(arr)— to return size (arrays/2D/keyed arrays or string length)array:head(arr)/array:last(arr)— to return first/last or_if emptyarray:nth(index, arr)— to return item atindex(negatives from end) or_array:includes(item, arr)— to test membershiparray:find(pred, arr)/array:findIndex(pred, arr)— to return first match or-1
2) Transformations
array:map(fn, arr)/array:filter(pred, arr)/array:reduce(fn, [init], arr)array:each(fn, arr)— to apply for side-effects, returning original dataarray:flatten(arr)/array:flatten_deep(arr)/array:compact(arr)/array:reverse(arr)array:slice(start, end, arr)/array:take(n, arr)/array:drop(n, arr)array:take_while(pred, arr)/array:drop_while(pred, arr)array:init(arr)/array:tail(arr)/array:range(start, end)/array:repeat(value, n)array:chunk(size, arr)— to chunk; returns typed 2D arrays for uniform numeric rows
All of the above are curry-able and accept _ as a placeholder.
3) Sorting & ordering
array:sort(arr)— to default-sort typed arrays or pass throughMixedArrayarray:sort_by(keyFn, arr)— to stable-sort by extracted keyarray:sort_with([cmp...], arr)— to stable-sort with one or more comparator functions
Comparators must return negative / zero / positive (int/long/float). Ties are stable.
4) Set operations & algebra
array:uniq(arr)/array:shuffle(arr)array:multi_union(a, b)/array:multi_intersection(a, b)/array:multi_difference(a, b)array:multi_concat(a, b)— to concatenate while preserving type when possible
5) Keyed arrays (objects)
array:keys(obj)— to returnStrArrayof keysarray:prop(key, obj)/array:pluck(key, arrayOfObjs)— to select propertiesarray:assoc(key, value, obj)— to upsert key/value (returns a new keyed array)array:key_eq(expected, key, obj)— to testobj[key] == expected(Ramda-likepropEq)array:group_by(keyFn, arr)— to return keyed array of groupedMixedArrayvalues
6) Iterators & flows
array:collect(iter)— to collect iterator values into a typed or mixed arrayarray:apply(fn, argsArrayOrIter)— to apply a function to a list/iterator of arguments- Works with core iterators (e.g.,
step(start, end)) and plugin iterators.
7) Zipping & composition helpers
array:zip(a, b)/array:zip_with(fn, a, b)array:append(item, arr)— to push or concatenate when stringsarray:join(sep, arr)— to join string collections
Calling style, currying & placeholders
All multi-arg functions support:
-
currying with
_placeholders:extend("array") onlyOdds = array:filter(x => x % 2 != 0) onlyOdds([1,2,3,4,5]) // [1,3,5] -
data-last ergonomics for many functions (e.g.,
map,filter,reduce,slice,take,drop):array:slice(1, -1, [10,20,30,40]) // [20,30] -
negative indices where natural (e.g.,
array:nth(-1, xs)picks the last element).
Return conventions
- Out-of-range access →
_ - Not found (
findIndex) →-1 - Predicate/Comparator type mismatches → descriptive errors (
"array:<fn> => ...") - Sorting is stable (equal keys keep original order)
Interop & type rules
- Typed arrays are preserved across operations:
IntArray,FloatArray,StrArray,BoolArray. - Heterogeneous inputs produce
MixedArray; many transforms up-cast to typed arrays when all elements agree. chunk(size, arr)returnsInt2DArray/Float2DArraywhen rows are uniform; otherwise aMixedArrayof row arrays.- Keyed-array results (
group_by,assoc) preserve insertion order of keys. applyaccepts function plusMixedArray/typed arrays/iterators as the argument list.mapintentionally rejects tensors in this build.
Minimal examples
extend("array")
xs = [1,2,3,4,5]
array:map(x => x * 2, xs) // [2,4,6,8,10]
array:filter(x => x % 2 == 0, xs) // [2,4]
array:reduce((acc, x) => acc + x, 0, xs) // 15
people = [[name:"Ada", age:36], [name:"Ben", age:29]]
array:keys(people[0]) // ["name","age"]
array:pluck("name", people) // ["Ada","Ben"]
array:sort_by(p => p:age, people) // age-ascending
// Partials & placeholders
take3 = array:take(3)
take3([9,8,7,6]) // [9,8,7]
assocCity = array:assoc("city")
assocCity("Oslo", [name:"Kai"]) // [name:"Kai", city:"Oslo"]
// Iterators
array:collect(step(3, 7)) // [3,4,5,6]
Design notes
- Typed results — to return concrete array types when homogeneous,
MixedArrayotherwise. - Stable sorts — to preserve relative order on ties in
sort_byandsort_with. - Data-last, placeholder-friendly — to encourage composition and partial application.
- Host vs. wasm — to compile on both:
- host: exports
Cargo_lockforextend("array") - wasm/embedded: call
array_mumu::register_all(&mut interp)
- host: exports
Status & caveats
array:mapcurrently rejectsTensorvalues.- Comparators must return numeric values; non-numeric returns are treated as ties or rejected where appropriate.
- Some functions coerce scalar arguments from single-element arrays (e.g., count/index from
IntArray([n])) for ergonomics.
Contributing
Issues and merge requests are welcome at:
https://gitlab.com/tofo/mumu-array
Please align changes with the MuMu core conventions:
- placeholder-aware currying
- data-last ergonomics where it reads naturally
- stable sorts and predictable type narrowing/widening
- wasm compatibility and clear error messages
License
Licensed under either of:
- MIT license
- Apache License, Version 2.0
at your option.