折叠和foldLeft或foldRight之间的区别?
注:我在Scala 2.8-可以是一个问题?
为什么我不能像foldLeft
或foldRight
一样使用fold
函数?
在设置scaladoc它说:
折叠的结果可能只是这个并行集合的types参数
T
的超types。
但是我在函数签名中看不到types参数T
:
def fold [A1 >: A] (z: A1)(op: (A1, A1) ⇒ A1): A1
foldLeft-Right
和fold
之间有什么区别,我如何使用后者?
编辑:例如,我将如何写一个折叠来添加列表中的所有元素? 随着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
,与foldRight
和foldLeft
相反,不能保证收集元素的处理顺序。 您可能会希望使用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