他のポスターは良い答えを与えてくれました、そして私は彼らがすでに言ったことを繰り返さないでしょう。質問でScalaの例を示したので、Scala固有の例を示します。トリックはすでに述べ、foldRight
維持する必要があるn-1
場合には、スタックフレームをn
およびもない尾再帰はここからあなたを救うことができる-あなたのリストの長さであり、これは簡単にスタックオーバーフローにつながることができます。
A 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)
これは、の実装でList
行われるように、繰り返し計算できます。
Scalaとして厳密に評価された言語では、a 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
、少なくともScala では常にを使用します。それ以外の場合は、回答に記載されている他のアドバイスを使用してください;)。