其他海报已经给出了很好的答案,我不会重复他们已经说过的话。正如你在你的问题中给出了一个Scala例子,我将给出一个Scala特定的例子。正如Tricks已经说过,一个foldRight
需要保留n-1
堆栈帧,其中n
是您的列表的长度,这很容易导致堆栈溢出 - 甚至连尾部递归都不能使你免于此。
甲List(1,2,3).foldRight(0)(_ + _)
将减少到:
1 + List(2,3).foldRight(0)(_ + _) // first stack frame
2 + List(3).foldRight(0)(_ + _) // second stack frame
3 + 0 // third stack frame
// (I don't remember if the JVM allocates space
// on the stack for the third frame as well)
List(1,2,3).foldLeft(0)(_ + _)
同时将减少到:
(((0 + 1) + 2) + 3)
可迭代计算,如在implementation of List
完成。
在一个严格评估的语言斯卡拉,foldRight
可以轻松地吹大堆列表,而foldLeft
不会。
例:因此
scala> List.range(1, 10000).foldLeft(0)(_ + _)
res1: Int = 49995000
scala> List.range(1, 10000).foldRight(0)(_ + _)
java.lang.StackOverflowError
at scala.List.foldRight(List.scala:1081)
at scala.List.foldRight(List.scala:1081)
at scala.List.foldRight(List.scala:1081)
at scala.List.foldRight(List.scala:1081)
at scala.List.foldRight(List.scala:1081)
at scala.List.foldRight(List.scala:1081)
at scala.List.foldRight(List.scala:1081)
at scala.List.foldRight(List.scala:1081)
at scala.List.foldRig...
我的经验法则是 - 对于不具有特定的关联性,始终使用foldLeft
,至少在斯卡拉运营商。否则,请与答案中给出的其他建议;)。
看起来类似于http:// stackoverflow。com/questions/384797/foldr-vs-foldl-or-foldl的含义 – 2009-09-18 20:57:25
这个Q比这更具一般性,特别是关于Haskell。懒惰对问题的答案有很大的影响。 – 2009-09-19 00:44:29
哦。奇怪的是,不知何故,我认为我在这个问题上看到了一个Haskell标签,但我猜不... – ephemient 2009-09-19 04:09:59