检测Python或动态语言中的无限递归
最近我尝试用GCC编译一个类似这样的程序:
int f(int i){
if(i<0){ return 0;}
return f(i-1);
f(100000);
结果运行得很好。当我查看堆栈帧时,发现编译器优化了这个程序,只用了一个堆栈帧,它通过跳回函数的开头来实现,只是替换了传给函数f的参数。而且——编译器甚至没有在优化模式下运行。
但是,当我在Python中尝试同样的事情时,我遇到了最大递归限制(如果我把递归深度设置得太高,可能会导致堆栈溢出)。
有没有办法让像Python这样的动态语言也能利用这些不错的优化呢?也许可以用编译器而不是解释器来实现这个效果?
我只是好奇!
3 个回答
6
当我检查程序的调用栈时,发现编译器优化了程序,只用了一个调用栈帧,它通过直接跳回函数的开头,并只替换参数来实现。
你说的这个情况叫做“尾递归”。有些编译器或解释器支持尾递归,有些则不支持。实际上,大多数是不支持的。正如你注意到的,gcc是支持的。而且,尾递归是Scheme编程语言规范的一部分,所以所有的Scheme编译器和解释器都必须支持尾递归。另一方面,像Java和Python这样的语言的编译器(我敢打赌大多数其他语言也是如此)并不支持尾递归。
像Python这样的动态语言有没有办法利用这些不错的优化呢?
你是问“现在”是否可以,还是在更抽象的层面上问?从抽象的角度来看,是的!动态语言完全可以利用尾递归的优化(比如Scheme就做到了)。但从具体的角度来看,不行,CPython(标准的Python解释器)没有任何标志或参数可以启用尾递归。