检测Python或动态语言中的无限递归

时间:2010-03-24 12:01:24

标签: python gcc compiler-construction

最近我尝试使用GCC编译类似的程序:

int f(int i){
    if(i<0){ return 0;}
    return f(i-1);
f(100000);

它运行得很好。当我检查堆栈帧时,编译器优化程序只使用一个帧,只需跳回函数的开头,只将参数替换为f。而且 - 编译器甚至没有以优化模式运行。

现在,当我在Python中尝试同样的事情时 - 我点击了最大递归墙(或者如果我将递归深度设置得太高,可能会发生堆栈溢出)。

像python这样的动态语言是否可以利用这些优秀的优化? 也许可以使用编译器而不是解释器来实现这个功能吗?

好奇!

3 个答案:

答案 0 :(得分:12)

您正在谈论的优化称为尾调用消除 - 递归调用展开到迭代循环中。

已经对此进行了一些讨论,但目前的情况是这不会被添加,至少对于cpython是正确的。有关讨论,请参阅Guido's blog entry

但是,存在some decorators操作函数来执行此优化。它们通常只能节省空间,而不是时间(事实上,它们通常较慢)

答案 1 :(得分:6)

  

当我检查堆栈帧时,编译器优化程序只使用一个帧,只需跳回函数的开头,只将参数替换为f。

您所描述的内容称为“尾递归”。有些编译器/口译员支持它,有些则不支持。事实上,大多数人都没有。正如你所注意到的,gcc确实如此。实际上,尾递归是Scheme编程语言规范的一部分,因此所有Scheme编译器/解释器必须支持尾递归。另一方面,Java和Python等语言的编译器(以及大多数其他语言,我都打赌)不进行尾递归。

  

像python这样的动态语言是否可以利用这些优秀的优化?

你的意思是,现在,还是你用更抽象的术语提问?抽象地说,是的!动态语言绝对有可能利用尾递归(例如,Scheme)。但具体来说,不,CPython(规范的Python解释器)没有标志或其他参数来启用尾递归。

答案 2 :(得分:4)

它与动态语言或它被解释的事实无关。 CPython只是没有实施Tail Recursion优化。您可能会发现JPython等。