我为pascal三角写了以下函数。为什么要打电话
pascal_cont(a-1, b-1, (x:Int) => pascal_cont(a, b-1, (y:Int) => cont(x + y)))
不是尾递归?
def pascal(c: Int, r: Int): Int = {
def pascal_cont(a:Int, b:Int, cont: (Int) => Int): Int = {
if (a==0 || a==b) cont(1)
else pascal_cont(a-1, b-1, (x:Int) => pascal_cont(a, b-1, (y:Int) => cont(x + y)))
}
pascal_cont(c,r,n => n)
}
答案 0 :(得分:4)
如果您在@tailrec
功能上添加pascal_cont
注释,则会收到以下错误:
[error] ....scala:18: could not optimize @tailrec annotated method pascal_cont: it contains a recursive call not in tail position
[error] pascal_cont(a-1, b-1, (x:Int) => pascal_cont(a, b-1, (y:Int)=> cont (x + y)))
[error] ^
[error] one error found
因此lambda表达式中的调用不在尾部位置,这就是为什么它不是尾递归
答案 1 :(得分:4)
Scala编译器无法优化任何(理论上)尾递归函数,因为它将它们转换为while循环。例如,它也无法优化相互尾递归函数。您可以使用trampoline模式来缓解此问题。
在Scala中,scala.util.control.TailCalls
包含必要的实用程序。这将转变为:
def pascal(c: Int, r: Int): Int = {
import scala.util.control.TailCalls._
def pascal_cont(a:Int, b:Int, cont: (Int) => TailRec[Int]): TailRec[Int] = {
if (a==0 || a==b) cont(1)
else tailcall {
pascal_cont(a-1, b-1, (x:Int) =>
pascal_cont(a, b-1, (y:Int) => cont(x + y)))
}
}
pascal_cont(c,r,n => done(n)).result
}