Reading this article about reduce vs fold in Scala http://josephmoniz.github.io/blog/2013/04/04/scala-reduce-vs-fold/ it states "you are taking some value of N and performing aggregation operations on it such that the end result is typically some value of <= N."
But is this statement false since summing over N values produces a value >= N ?
Update : I think <= in this case means same type or sub-type
fold calls fold on an iterator for each partition, then merges the results, reduce calls reduceLeft on the iterator for each partition then merges the result. The difference is that fold doesn't need to worry about empty partitions or collections, because then it will just use the zero value.
Kotlin reduce is one of the default methods in the language used to transform or convert the given set of data collections into the single set output results. It also takes the lambda function to operate and combine the pair of data elements. It traverses from the left side to the right side of data collections.
The reduce() method transforms a given collection into a single result. It takes a lambda function operator to combine a pair of elements into a so-called accumulated value. It then traverses the collection from left to right and stepwise combines the accumulated value with the next element.
fold takes an initial value, and the first invocation of the lambda you pass to it will receive that initial value and the first element of the collection as parameters. For example, take the following code that calculates the sum of a list of integers: listOf(1, 2, 3).fold(0) { sum, element -> sum + element }
I think it's a flawed characterization. It's better to think of fold like this:
In: initial value way to combine stuff with initial value collection Out: combined stuff
And reduce is like this:
In: way to combine stuff collection Out: combined stuff
That is, the difference is whether you have an initial value (which might not even be of the same type as what you've got in the collection!), as fold does, or whether you just collapse the values you already have, as reduce does.
If you have a natural zero, that is, something that can be combined without changing what it combines with, then you can implement reduce as a fold starting with a zero. For example, for multiplication the zero is 1
(because 1*x == x
), so
List(1,2,3).fold(1){_ * _} List(1,2,3).reduce{_ * _}
give the same answer. (Only the first gives an answer on an empty list, however!)
To see an example of how fold is entirely more general, consider this one--here with a foldLeft so we know to pass the initial value in on the left-hand 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)
.
Fold needs "starting element" be provided, reduce will automatically take 1st element of sequence as starting, so they are kind of equivalent for some degree:
val L = List(1,2,3,4) val H = L.head val T = L.tail L.reduce(_+_) ~== T.fold(H)(_+_)
Reduce more compact, but with fold you have ability to provide different start element and change result of the operation, so:
2014 + L.reduce(_+_) ~== L.fold(2014)(_+_) // NB: here we use L, not T for fold
Things will be more exciting and more favorable for fold when you will step out of simple arithmetics to some more complex binary operations like Set + Int:
List(1,2,3,3,2,2,1).foldLeft(Set[Int]())(_ + _) // will produce Set(1, 2, 3)
... you can fold an JDBC update call :).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With