What is basic difference between fold and reduce in Kotlin? When to use which?

﹥>﹥吖頭↗ 提交于 2019-11-28 19:25:54

问题


I am going through basics of Kotlin and I am pretty confused with this both functions fold() and reduce() in Kotlin, can anyone give me a concrete example which distinguishes both of them?


回答1:


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 }

The first call to the lambda will be with parameters 0 and 1.

Having the ability to pass in an initial value is useful if you have to provide some sort of default value or parameter for your operation. For example, if you were looking for the maximum value inside a list, but for some reason want to return at least 10, you could do the following:

listOf(1, 6, 4).fold(10) { max, element ->
    if (element > max) element else max
}

reduce doesn't take an initial value, but instead starts with the first element of the collection as the accumulator (called sum in the following example).

For example, let's do a sum of integers again:

listOf(1, 2, 3).reduce { sum, element -> sum + element }

The first call to the lambda here will be with parameters 1 and 2.

You can use reduce when your operation does not depend on any values other than those in the collection you're applying it to.




回答2:


The major functional difference I would call out (which is mentioned in the comments on the other answer, but may be hard to understand) is that reduce will throw an exception if performed on an empty collection.

listOf<Int>().reduce { x, y -> x + y }
// java.lang.UnsupportedOperationException: Empty collection can't be reduced.

This is because .reduce doesn't know what value to return in the event of "no data".

Contrast this with .fold, which requires you to provide a "starting value", which will be the default value in the event of an empty collection:

val result = listOf<Int>().fold(0) { x, y -> x + y }
assertEquals(0, result)

So, even if you don't want to aggregate your collection down to a single element of a different (non-related) type (which only .fold will let you do), if your starting collection may be empty then you must either check your collection size first and then .reduce, or just use .fold

val collection: List<Int> = // collection of unknown size

val result1 = if (collection.isEmpty()) 0
              else collection.reduce { x, y -> x + y }

val result2 = collection.fold(0) { x, y -> x + y }

assertEquals(result1, result2)


来源:https://stackoverflow.com/questions/44429419/what-is-basic-difference-between-fold-and-reduce-in-kotlin-when-to-use-which

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!