Fold and foldLeft method difference

后端 未结 7 805
终归单人心
终归单人心 2021-01-31 01:51

I am not sure what is the difference between fold and foldLeft in Scala.

The question Difference between fold and foldLeft or foldRight? has an

7条回答
  •  一生所求
    2021-01-31 02:07

    The error. You are getting a compile-time error because the signature of fold only allows folding values of type which is the supertype of the type of the values in the collection, and the only supertype of String (your collection type) and Int (the type of your provided zero element) is Any. So, the type of the fold result is inferred to be Any - and Any does not have a method toInt.

    Note that the two versions of fold have different signatures:

    fold[A1 >: A](z: A1)(op: (A1, A1) => A1): A1
    
    foldLeft[B](z: B)(f: (B, A) => B): B
    

    Why do they have different signatures? This is because fold could be implemented in parallel, as is the case with parallel collections. When multiple processors fold over the values in the collections, each one of the processors takes a subset of elements of type A and produces the folded value of type A1, by consecutively applying op. The results produced by those processors must be combined together into a final folding value - this is done using the op function, which does exactly that.

    Now, note that this cannot be done using the f in foldLeft, because each of the processors produces a folded value of type B. Several values of type B cannot be combined using f, because f only combines value B with another value of type A - there is no correspondance between types A and B.

    Example. In your example, assume the 1st processor takes elements "1", "2" and the 2nd takes element "3". The first one will produce the folded value 3, and the second will produce another folded value 3. Now they have to combine their results to get the final folded value - this is impossible, because the closure _ + _.toInt only knows how to combine an Int and String, and not 2 Int values.

    For situations where these types differ, use aggregate, in which you have to define how to combine two values of type B:

    def aggregate[B](z: B)(seqop: (B, A) => B, combop: (B, B) => B): B
    

    The combop above defines how to do the final step when the fold result and the elements in the collection have different types.

    The neutral element. As described above, multiple processors may fold over subsets of elements in the collection. Each one of them will start its folded value by adding the neutral element.

    In the following example:

    List(1, 2, 3).foldLeft(4)(_ + _)
    

    always returns 10 = 4 + 1 + 2 + 3.

    However, 4 should not be used with fold, as it is not a neutral element:

    List(1, 2, 3).fold(4)(_ + _)
    

    The above may return (4 + 1 + 2) + (4 + 3) = 14 or (4 + 1) + (4 + 2) + (4 + 3) = 18. If you don't use the neutral element for the fold, the results are nondeterministic. In the same way, you can use the Nil as a neutral element, but not a non-empty list.

提交回复
热议问题