# 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; `MixedArray` otherwise)
- 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 empty
- `array:nth(index, arr)` — to return item at `index` (negatives from end) or `_`
- `array:includes(item, arr)` — to test membership
- `array: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 data
- `array: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 through `MixedArray`
- `array:sort_by(keyFn, arr)` — to stable-sort by extracted key
- `array: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 return `StrArray` of keys
- `array:prop(key, obj)` / `array:pluck(key, arrayOfObjs)` — to select properties
- `array:assoc(key, value, obj)` — to upsert key/value (returns a new keyed array)
- `array:key_eq(expected, key, obj)` — to test `obj[key] == expected` (Ramda-like `propEq`)
- `array:group_by(keyFn, arr)` — to return keyed array of grouped `MixedArray` values
### 6) Iterators & flows
- `array:collect(iter)` — to collect iterator values into a typed or mixed array
- `array: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 strings
- `array:join(sep, arr)` — to join string collections
---
## Calling style, currying & placeholders
All multi-arg functions support:
- **currying** with `_` placeholders:
```mu
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`):
```mu
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)` returns `Int2DArray` / `Float2DArray` when rows are uniform; otherwise a `MixedArray` of row arrays.
- Keyed-array results (`group_by`, `assoc`) preserve insertion order of keys.
- `apply` accepts function plus `MixedArray`/typed arrays/iterators as the argument list.
- `map` intentionally rejects tensors in this build.
---
## Minimal examples
```mu
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, `MixedArray` otherwise.
- **Stable sorts** — to preserve relative order on ties in `sort_by` and `sort_with`.
- **Data-last, placeholder-friendly** — to encourage composition and partial application.
- **Host vs. wasm** — to compile on both:
- host: exports `Cargo_lock` for `extend("array")`
- wasm/embedded: call `array_mumu::register_all(&mut interp)`
---
## Status & caveats
- `array:map` currently rejects `Tensor` values.
- 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.