[英]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.