F2.05 · part 3 of 4
reduce
Reduce is the general fold — the one map and filter are built from. Its power is that the accumulator can be any shape. A number gives you a sum; a list lets you rebuild the collection; a map lets you tally or index it.
The hub showed reduce collapsing a list to a number. The accumulator does not have to stay a number. Start it as an empty list and reduce builds a list; start it as an empty map and reduce builds a map. The combiner decides how each element folds into whatever the accumulator is.
Accumulators of any shape
The accumulator’s type is your choice. The same reduce skeleton sums to a number, rebuilds a list, or constructs a map — the difference is the starting value and how the combiner folds each element in.
Choose what the accumulator is.
- reduce
- fold a list into a single value of any type.
- accumulator
- the value carried through; it can be a number, list, map, or tuple.
- initial value
- what the accumulator starts as — the result for the empty list.
- reducer
- the combiner:
fn element, acc -> new_acc end.
One reduce, three accumulator types
Idea
The accumulator’s type decides what you are building — a total, a list, or a table.
F2.05 · universal
A list accumulator is how map and filter fall out of reduce.
Pick the accumulator and you pick the result type. Reduce is one skeleton over many shapes.
Build a map
With a map accumulator, reduce tallies. Starting from an empty map, each element bumps its own count.
Map.update(acc, key, 1, &(&1 + 1)) sets the count to 1 the first time a key is
seen and increments it after.
Step through counting the elements.
reduce([:a, :b, :a, :c, :a], %{}, …) · tally into a map
Idea
The map grows one key at a time; repeats bump a count instead of adding a key.
Elixir
Enum.frequencies/1 is this exact fold, packaged.
A map accumulator turns reduce into a tally. The same step pattern indexes, groups, or counts.
Worked examples
Four reduces, four accumulator shapes: a number, a tuple, a map, and an early exit.