I consider this an erroneous characteristic. Itβs better to think of it this way:
In: initial value way to combine stuff with initial value collection Out: combined stuff
And reduce it like this:
In: way to combine stuff collection Out: combined stuff
That is, the difference is whether you have an initial value (which may not even be the same type as your collection!), As the fold does, or just dump the values ββthat you already have, as the reduction does .
If you have a natural zero, that is, something that can be combined without changing what it is combined with, then you can implement a reduction in the form of a reset, starting from zero. For example, for multiplication, zero is 1 (because 1*x == x ), therefore
List(1,2,3).fold(1){_ * _} List(1,2,3).reduce{_ * _}
give the same answer. (However, only the first gives an answer in an empty list!)
To see an example of how fold is completely more general, consider this: here with foldLeft so that we know that the initial value is passed on the left side of the operation -
List(1,2,3).foldLeft(List(0))((ns,n) => ns ++ List.fill(n+1)(n))
which gives List(0, 1, 1, 2, 2, 2, 3, 3, 3, 3) .