其他海報已經給出了很好的答案,我不會重複他們已經說過的話。正如你在你的問題中給出了一個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