06 / DATA
mr
A mapper that sees one item and emits any number of values, a finish step for the aggregate that only makes sense at the end, and a reducer over everything emitted — sequentially or across tasks, with the parallel run emitting in input order.
WHERE IT SITS
INTERFACE
struct Mapper[A, B]structA mapper: map sees one item and emits values with emit; finish runs after the last item, for whatever an aggregate can only produce once the stream is done.
fn[A, B] Mapper::new( map~ : (A, (B) -> Unit) -> Unit, finish~ : ((B) -> Unit) -> Unit = _emit => ()) -> Mapper[A, B]itemA mapper from a function that emits per item. finish does nothing unless one is given.
fn[A, B] Mapper::one(f : (A) -> B) -> Mapper[A, B]itemA mapper that emits exactly one value per item — the common case.
fn[A, B, C] map_reduce( source : Array[A], mapper : Mapper[A, B], reducer : (Array[B]) -> C) -> CitemRun mapper over source and hand every emitted value to reducer, in the order the items were visited.
async fn[A, B, C] map_reduce_parallel( source : Array[A], mapper : Mapper[A, B], reducer : (Array[B]) -> C, max_concurrent~ : Int32 = 4) -> Citemmap_reduce with the mapping split across at most max_concurrent tasks. The items are cut into one run per task, each run emits into its own array, and the arrays are concatenated in slice order — so the result is the same one the sequential run produces, whatever order the tasks happened to finish in.