Scala:fold vs foldLeft [英] Scala : fold vs foldLeft

查看:161
本文介绍了Scala:fold vs foldLeft的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图了解fold和foldLeft以及各自的reduce和reduceLeft的工作方式.我以fold和foldLeft为例.

I am trying to understand how fold and foldLeft and the respective reduce and reduceLeft work. I used fold and foldLeft as my example

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)

为什么fold不能用作foldLeft?什么是Serializable with Equals?我了解fold和foldLeft在参数泛型类型方面具有稍微不同的API签名.请指教.谢谢.

Why fold didn't work as foldLeft? What is Serializable with Equals? I understand fold and foldLeft has slight different API signature in terms of parameter generic types. Please advise. Thanks.

推荐答案

就可以应用的类型而言,方法fold(最初为并行计算而添加)的功能不及foldLeft.它的签名是:

The method fold (originally added for parallel computation) is less powerful than foldLeft in terms of types it can be applied to. 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

原因是fold可以并行实现,而foldLeft不能并行实现.这不仅是因为*Left部分意味着foldLeft从左到右顺序进行,而且还因为运算符op无法合并并行计算的结果-它仅定义如何合并聚合类型<元素类型为A的c10>,但不是如何组合类型为B的两个聚合的c10>.反之,fold方法确实定义了此方法,因为聚合类型A1必须是元素类型A的超类型,即A1 >: A.这种超类型关系允许在同一时间折叠聚合和元素,并结合聚合-两者都使用一个运算符.

The reason is that fold can be implemented in parallel, while foldLeft cannot. 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. 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. This supertype relationship allows in the same time folding over the aggregation and elements, and combining aggregations -- both with a single operator.

但是,聚合和元素类型之间的这种超类型关系也意味着您示例中的聚合类型A1应该是(ArrayBuffer[Int], Int)的超类型.由于聚合的零元素是类型为ArrayBuffer[Int]ArrayBuffer(1, 2, 4, 5),因此聚合类型被推断为这两种类型的超类型-即Serializable with Equals,这是元组和数组的唯一最小上限缓冲.

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). 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.

通常,如果要允许任意类型的并行折叠(不按顺序进行),则必须使用方法aggregate,该方法需要定义如何合并两个聚合.就您而言:

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. In your case:

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

顺便说一句,尝试使用reduce/reduceLeft编写示例-由于这两种方法都具有元素类型和聚合类型之间的超类型关系,因此您会发现它导致了与您描述过的那一个.

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.

这篇关于Scala:fold vs foldLeft的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆