Functional Programming in Scala列出了以下关于合成函数如何导致StackOverflowError
的示例。
scala> val f = (x: Int) => x
f: Int => Int = <function1>
scala> val g = List.fill(100000)(f).foldLeft(f)(_ compose _)
g: Int => Int = <function1>
scala> g(42)
java.lang.StackOverflowError
正如本书所解释的那样,g
是一个复合函数,它有100,000个函数,每个函数都调用下一个函数。
由于foldLeft
是尾递归的,为什么会出现StackOverflowError?如果有的话,尾递归和StackOverflow是如何相关的?
当(扩展)(B, A) => B
,foldLeft
的第二个参数((acc, elem) => acc.compose(elem))
时,每个折叠步骤不会导致只编写2个函数吗?
答案 0 :(得分:6)
由于foldLeft是尾递归的,为什么会出现StackOverflowError?如果有的话,尾递归和StackOverflow是如何相关的?
当(扩展时)第二个参数(B,A)=&gt; foldLeft的B,((acc,elem)=&gt; acc.compose(elem)),每个折叠步骤不会只组成2个函数吗?
请注意,折叠本身(即行val g = ...
)不会溢出堆栈。但是,g
最终被有效地定义为f(f(...(x)))
,因此您需要100000个堆栈帧来评估显然会溢出的g(42)
。
答案 1 :(得分:5)
这不是因为foldLeft
或compose
本身。这是因为g(x) = f(f(f(...(x)))
。