简体   繁体   English

Scala:fold vs foldLeft

[英]Scala : fold vs foldLeft

I am trying to understand how fold and foldLeft and the respective reduce and reduceLeft work. 我试图了解fold和foldLeft以及各自的reduce和reduceLeft是如何工作的。 I used fold and foldLeft as my example 我用fold和foldLeft作为例子

scala> val r = List((ArrayBuffer(1, 2, 3, 4),10))
scala> r.foldLeft(ArrayBuffer(1,2,4,5))((x,y) => x -- y._1)

scala> res28: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(5)

scala> r.fold(ArrayBuffer(1,2,4,5))((x,y) => x -- y._1)
<console>:11: error: value _1 is not a member of Serializable with Equals
              r.fold(ArrayBuffer(1,2,4,5))((x,y) => x -- y._1)

Why fold didn't work as foldLeft ? 为什么fold不能作为foldLeft What is Serializable with Equals ? 什么是Serializable with Equals I understand fold and foldLeft has slight different API signature in terms of parameter generic types. 我理解fold和foldLeft在参数泛型类型方面有轻微不同的API签名。 Please advise. 请指教。 Thanks. 谢谢。

The method fold (originally added for parallel computation) is less powerful than foldLeft in terms of types it can be applied to. 方法fold (最初为并行计算添加)在可应用的类型方面不如foldLeft强大。 Its signature is: 它的签名是:

def fold[A1 >: A](z: A1)(op: (A1, A1) => A1): A1

This means that the type over which the folding is done has to be a supertype of the collection element type. 这意味着完成折叠的类型必须是集合元素类型的超类型。

def foldLeft[B](z: B)(op: (B, A) => B): B

The reason is that fold can be implemented in parallel, while foldLeft cannot. 原因是fold可以并行实现,而foldLeft则不能。 This is not only because of the *Left part which implies that foldLeft goes from left to right sequentially, but also because the operator op cannot combine results computed in parallel -- it only defines how to combine the aggregation type B with the element type A , but not how to combine two aggregations of type B . 这不仅是因为*Left部分暗示foldLeft顺序从左向右,而且因为运算符op不能组合并行计算的结果 - 它只定义了如何将聚合类型B与元素类型A ,但不是如何组合B类型的两个聚合。 The fold method, in turn, does define this, because the aggregation type A1 has to be a supertype of the element type A , that is A1 >: A . 反过来, fold方法确实定义了这个,因为聚合类型A1必须是元素类型A的超类型,即A1 >: A This supertype relationship allows in the same time folding over the aggregation and elements, and combining aggregations -- both with a single operator. 这种超类型关系允许同时折叠聚合和元素,以及组合聚合 - 两者都与单个运算符相结合。

But, this supertype relationship between the aggregation and the element type also means that the aggregation type A1 in your example should be the supertype of (ArrayBuffer[Int], Int) . 但是,聚合和元素类型之间的这种超类型关系也意味着示例中的聚合类型A1应该是(ArrayBuffer[Int], Int)的超类型。 Since the zero element of your aggregation is ArrayBuffer(1, 2, 4, 5) of the type ArrayBuffer[Int] , the aggregation type is inferred to be the supertype of both of these -- and that's Serializable with Equals , the only least upper bound of a tuple and an array buffer. 由于聚合的零元素是ArrayBuffer(1, 2, 4, 5) ArrayBuffer[Int]类型的ArrayBuffer[Int] ,因此聚合类型被推断为这两者的超类型 - 并且可以Serializable with Equals ,这是唯一的元组的上限和数组缓冲区。

In general, if you want to allow parallel folding for arbitrary types (which is done out of order) you have to use the method aggregate which requires defining how two aggregations are combined. 通常,如果要允许任意类型的并行折叠(这不按顺序执行),则必须使用方法aggregate ,这需要定义两个聚合的组合方式。 In your case: 在你的情况下:

r.aggregate(ArrayBuffer(1, 2, 4, 5))({ (x, y) => x -- y._1 }, (x, y) => x intersect y)

Btw, try writing your example with reduce / reduceLeft -- because of the supertype relationship between the element type and the aggregation type that both these methods have, you will find that it leads to a similar error as the one you've described. 顺便说一句,尝试使用reduce / reduceLeft编写示例 - 由于这两种方法都具有元素类型和聚合类型之间的超类型关系,您会发现它会导致与您所描述的类似的错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM