折叠和foldLeft或foldRight之间的区别?

注:我在Scala 2.8-可以是一个问题?

为什么我不能像foldLeftfoldRight一样使用fold函数?

在设置scaladoc它说:

折叠的结果可能只是这个并行集合的types参数T的超types。

但是我在函数签名中看不到types参数T

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

foldLeft-Rightfold之间有什么区别,我如何使用后者?

编辑:例如,我将如何写一个折叠来添加列表中的所有元素? 随着foldLeft这将是:

 val foo = List(1, 2, 3) foo.foldLeft(0)(_ + _) // now try fold: foo.fold(0)(_ + _) >:7: error: value fold is not a member of List[Int] foo.fold(0)(_ + _) ^ 

你是正确的旧版本的斯卡拉是一个问题。 如果您查看Scala 2.8.1的scaladoc页面 ,您将看到在那里没有定义折叠(与您的错误消息一致)。 显然,在Scala 2.9中引入了fold

简短的回答:

foldRight同右。 即元素将按从右到左的顺序累加:

 List(a,b,c).foldRight(z)(f) = f(a, f(b, f(c, z))) 

foldLeft同左。 即一个累加器将被初始化,元素将按照从左到右的顺序被添加到累加器中:

 List(a,b,c).foldLeft(z)(f) = f(f(f(z, a), b), c) 

fold联合的 ,因为元素被添加在一起的顺序没有被定义。 即要fold形成一个幺半群的论据。

fold ,与foldRightfoldLeft相反,不能保证收集元素的处理顺序。 您可能会希望使用fold ,与更多的约束签名,并行集合,其中缺乏有保证的处理顺序有助于并行集合实现并行折叠。 更改签名的原因是相似的:有了额外的约束,更容易进行平行折叠。

对于您的特定示例,您可以使用与foldLeft相同的方式进行编码。

 val ns = List(1, 2, 3, 4) val s0 = ns.foldLeft (0) (_+_) //10 val s1 = ns.fold (0) (_+_) //10 assert(s0 == s1) 

同意其他答案。 想到给一个简单的例子说明:

  object MyClass { def main(args: Array[String]) { val numbers = List(5, 4, 8, 6, 2) val a = numbers.fold(0) { (z, i) => { println("fold val1 " + z +" val2 " + i) z + i } } println(a) val b = numbers.foldLeft(0) { (z, i) => println("foldleft val1 " + z +" val2 " + i) z + i } println(b) val c = numbers.foldRight(0) { (z, i) => println("fold right val1 " + z +" val2 " + i) z + i } println(c) } } 

结果是自我解释的:

 fold val1 0 val2 5 fold val1 5 val2 4 fold val1 9 val2 8 fold val1 17 val2 6 fold val1 23 val2 2 25 foldleft val1 0 val2 5 foldleft val1 5 val2 4 foldleft val1 9 val2 8 foldleft val1 17 val2 6 foldleft val1 23 val2 2 25 fold right val1 2 val2 0 fold right val1 6 val2 2 fold right val1 8 val2 8 fold right val1 4 val2 16 fold right val1 5 val2 20 25