array-mumu 0.2.0-rc.5

Array tools plugin for the Mumu ecosystem
Documentation
# 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.