algo
.zn moduleFunctional collection utilities. Pure Zinc, no native code. import "algo". Fully generic (<T>/<T,U>/<T,K>) — the signatures below show each function's own type parameters; T/U/K are inferred at the call site, same as any other generic function (see the Generics section above).
sort_by/min_by/max_by compare via the key's own type (</>), so numeric keys sort numerically. unique/unique_by use real deep equality (==/!=), not string coercion. A call through the module (algo.filter(xs, pred)) is not yet argument-type-checked at the call site — the type checker doesn't track an imported module's exports (see docs/roadmap-to-1.0.md's Phase 2 status). algo.zn's own signatures are correct and self-consistent (its body type-checks cleanly); a caller passing the wrong argument type just won't be caught until runtime, same as before this migration.algo.filter<T>(list: [T], pred: (T) => bool) => [T]algo.map_fn<T, U>(list: [T], f: (T) => U) => [U]algo.reduce<T, U>(list: [T], f: (U, T) => U, init: U) => Ualgo.each<T>(list: [T], f: (T))algo.find<T>(list: [T], pred: (T) => bool) => (T, bool)algo.find_index<T>(list: [T], pred: (T) => bool) => intalgo.any<T>(list: [T], pred: (T) => bool) => boolalgo.all<T>(list: [T], pred: (T) => bool) => boolalgo.count<T>(list: [T], pred: (T) => bool) => intalgo.zip<T, U>(a: [T], b: [U]) => [[any]]algo.flatten<T>(list: [[T]]) => [T]algo.take<T>(list: [T], n: int) => [T]algo.drop<T>(list: [T], n: int) => [T]algo.take_while<T>(list: [T], pred: (T) => bool) => [T]algo.drop_while<T>(list: [T], pred: (T) => bool) => [T]algo.chunk<T>(list: [T], n: int) => [[T]]algo.unique<T>(list: [T]) => [T]algo.unique_by<T, K>(list: [T], key_fn: (T) => K) => [T]algo.group_by<T>(list: [T], key_fn: (T) => string) => [string, [T]]algo.sort<T>(list: [T], cmp: (T, T) => bool) => [T]algo.sort_by<T, K>(list: [T], key_fn: (T) => K) => [T]algo.min_by<T, K>(list: [T], key_fn: (T) => K) => (T, bool)algo.max_by<T, K>(list: [T], key_fn: (T) => K) => (T, bool)algo.sum(list: [any]) => int|floatalgo.product(list: [any]) => int|floatalgo.reverse<T>(list: [T]) => [T]algo.concat<T>(a: [T], b: [T]) => [T]algo.intersperse<T>(list: [T], sep: T) => [T]algo.window<T>(list: [T], n: int) => [[T]]
algo.filter<T>(list: [T], pred: (T) => bool) => [T]
Keep elements where pred is true.
algo.map_fn<T, U>(list: [T], f: (T) => U) => [U]
Transform each element.
algo.reduce<T, U>(list: [T], f: (U, T) => U, init: U) => U
Left fold with accumulator init.
algo.each<T>(list: [T], f: (T))
Side-effecting iteration.
algo.find<T>(list: [T], pred: (T) => bool) => (T, bool)
First matching element; bool is false if none.
algo.find_index<T>(list: [T], pred: (T) => bool) => int
Index of first match, or -1.
algo.any<T>(list: [T], pred: (T) => bool) => bool
True if any element matches.
algo.all<T>(list: [T], pred: (T) => bool) => bool
True if all elements match.
algo.count<T>(list: [T], pred: (T) => bool) => int
Number of matching elements.
algo.zip<T, U>(a: [T], b: [U]) => [[any]]
Pair elements by index (length = shorter); the pair itself stays [any] — there's no tuple type to express a mixed T/U pair.
algo.flatten<T>(list: [[T]]) => [T]
Remove one level of nesting.
algo.take<T>(list: [T], n: int) => [T]
First n elements.
algo.drop<T>(list: [T], n: int) => [T]
All but the first n.
algo.take_while<T>(list: [T], pred: (T) => bool) => [T]
Leading run where pred holds.
algo.drop_while<T>(list: [T], pred: (T) => bool) => [T]
Skip the leading run, return the rest.
algo.chunk<T>(list: [T], n: int) => [[T]]
Split into groups of size n (last may be short).
algo.unique<T>(list: [T]) => [T]
Remove consecutive duplicates (deep value equality) — NOT a global dedup, see unique_by.
algo.unique_by<T, K>(list: [T], key_fn: (T) => K) => [T]
Remove all dups globally by extracted key — different result shape than unique, not just a custom-key version of it.
algo.group_by<T>(list: [T], key_fn: (T) => string) => [string, [T]]
Group into a map of lists.
algo.sort<T>(list: [T], cmp: (T, T) => bool) => [T]
Stable insertion sort; cmp(a,b) true means a first.
algo.sort_by<T, K>(list: [T], key_fn: (T) => K) => [T]
Sort by extracted key.
algo.min_by<T, K>(list: [T], key_fn: (T) => K) => (T, bool)
Minimum by key; bool false if empty.
algo.max_by<T, K>(list: [T], key_fn: (T) => K) => (T, bool)
Maximum by key; bool false if empty.
algo.sum(list: [any]) => int|float
Sum; int if every element is an int, float if any element is a float. Not generic — a homogeneous [T] can't express a genuinely mixed int/float list.
algo.product(list: [any]) => int|float
Product; same mixed-list reasoning as sum, not generic.
algo.reverse<T>(list: [T]) => [T]
Reversed copy.
algo.concat<T>(a: [T], b: [T]) => [T]
Concatenate two lists.
algo.intersperse<T>(list: [T], sep: T) => [T]
Insert sep between elements.
algo.window<T>(list: [T], n: int) => [[T]]
Sliding windows of size n.