这个尾巴为什么递归?
问题描述:
退房这个斯卡拉代码:这个尾巴为什么递归?
def rec(n: Int) {
if (n > 1) {
val d = n/2
rec(d)
// if (d > 1) // abort loop
rec(n/d)
}
}
该代码将导致死循环。由于尾递归优化,我没有得到一个StackOverflowError。
用JAD反编译,我得到这个Java的代码:
public void rec(int n)
{
int d;
for(; n > 1; n /= d)
{
int i = n;
d = i/2;
rec(d);
}
}
在循环的方法调用本身,因此我不明白的尾调用位置的最后一行。任何人都可以解释这一点?
答
在rec(d)
的情况下没有尾部呼叫。对于rec(N)
(其中N > 1
)堆栈在log2(N)
调用后不再生长(因为此后n
永远等于2或3,且d
为1)。之后,它只是无限循环,每次立即返回内部rec(1)
调用。这就是为什么没有堆栈溢出。
答
在您的方法的递归形式中,您有两个递归调用。 StackOverflowError
是由最后一个造成的。
由于尾递归优化,最后一次调用变为循环(而第一次调用保持递归),因此你有无限循环而不是无限递归,并且StackOverflowError
不会发生。
这将是有益的1.http://www.cs.wayne.edu/~artem/main/teaching/csc3200ss2006/slides/recursion/types.html 2.http://stackoverflow.com/questions/ 105834 /做最JVM-防止尾叩优化 – 2011-03-17 09:43:03