61. Iterator::reduce — Fold Without an Initial Value
Using fold but your accumulator starts as the first element anyway? Iterator::reduce cuts out the boilerplate and handles empty iterators gracefully.
The fold pattern you keep writing
When finding the longest string, maximum value, or combining elements, fold forces you to pick an initial value — often awkwardly:
| |
That empty string "" is a code smell — it’s not a real element, it’s just satisfying fold’s signature. And if the input is empty, you silently get "" back instead of knowing there was nothing to reduce.
Enter reduce
Iterator::reduce uses the first element as the initial accumulator. No seed value needed, and it returns Option<T> — None for empty iterators:
| |
The Option return makes the empty case explicit — no more silent defaults.
Finding extremes without max_by
reduce is perfect for custom comparisons where max_by feels heavy:
| |
Concatenating without an allocator seed
Building a combined result from parts? reduce avoids allocating an empty starter:
| |
Compare this to fold(String::new(), ...) — with reduce, the first String becomes the accumulator directly, saving one allocation.
reduce vs fold — when to use which
Use reduce when the accumulator is the same type as the elements and there’s no meaningful “zero” value. Use fold when you need a different return type or a specific starting value:
| |
reduce has been stable since Rust 1.51 — it’s the functional programmer’s best friend for collapsing iterators when the first element is your natural starting point.