为什么这个尾递归:
pre
虽然不是这样:
def navigate(myList : List[Int]) : (Int, List[Int]) = {
def navigate(step: Int, offset: Int, myList: List[Int]): (Int, scala.List[Int]) = {
if //some test and exit condition, then a definition of jump
else navigate(step + 1, offset + jump, myList)
}
navigate(0, 0, myList)
}
如果def navigate(myList : List[Int]) : (Int, List[Int]) = {
navigate(0, 0, myList)
}
def navigate(step: Int, offset: Int, myList: List[Int]): (Int, scala.List[Int]) = {
if //some test and exit condition, then a definition of jump
else navigate(step + 1, offset + jump, myList)
}
非常长,则第一种情况不会产生任何问题,而第二种情况会导致myList
。
另外,有没有办法说编译器应该编译后者,以便递归不会增加堆栈?
答案 0 :(得分:4)
为了使方法符合尾递归优化的条件,它必须:
return
final
你的两个例子都符合#1和#2,但只有第一个例子符合#3(本地方法是隐式最终的)。
如果方法不是final
,那么方法不是尾递归的原因是“尾递归”意味着“尾调用自身”,但如果方法是虚拟的,那么你不能知道它是自己尾调用还是自我覆盖的版本。在编译时弄清楚方法是否被覆盖需要类层次结构分析,这已知等同于解决暂停问题... IOW是不可能的。
另外,有没有办法说编译器应该编译后者,以便递归不会增加堆栈?
没有。没有办法打开或关闭尾递归优化。尾递归的方法(根据Scala语言规范的“尾递归”的定义,当然)总是优化。任何不执行此操作的Scala实现都违反了Scala语言规范。
然而,是,scala.annotation.tailrec
注释,它保证如果使用此注释注释的方法不符合SLS的尾部定义,编译器将生成错误-recursion。