tee3

Three folds over one pass of a source — tee with one more reduction.

typedef Fold<A, R> = ({R seed, R Function(R acc, A a) step}); (R1, R2, R3) tee3<A, R1, R2, R3>(Iterable<A> iterable, Fold<A, R1> first, Fold<A, R2> second, Fold<A, R3> third)

Lecture

tee3 is tee with a third fold. Everything the tee page explains holds unchanged — each element advances every accumulator before the next one is pulled, so the source is iterated exactly once and nothing is buffered; the accumulators are independent and need not share a type; and the readers must be folds rather than pipelines. Read that page first for the reasoning and for where fork is the better tool.

Dart has no variadic generics, so each arity is its own function — the same reason zip is joined by zip3. Two and three cover the cases worth naming; beyond that, fold into a small record or class of your own and use plain fold.

Demo · Total, peak and count from one read

sensor() counts its own values. Three separate passes would leave reads at 18; tee3 leaves it at 6:

Related: tee — the two-fold form, and the full explanation · fork — independent readers, at the cost of a buffer · fold — a single fold