如果我定义了一个简单的尾递归函数:
function tailtest(n)
if n==0; feature memstats; return; end
tailtest(n-1);
end
并且调用它使得它会进行相当深的递归:
set(0,'RecursionLimit',10000);
tailtest(1000);
那么看起来堆栈帧并没有占用太多的内存。但是,如果我让它递归得更深:
set(0,'RecursionLimit',10000);
tailtest(5000);
然后(在我的机器上,今天)MATLAB 直接崩溃:进程突然死亡。
我认为这与 MATLAB 进行任何尾调用优化是不一致的;当一个函数仅在一个地方进行自我尾调用时,没有除一个参数外的局部变量,这种情况就足够简单了。
所以:不,似乎 MATLAB 默认情况下根本不会进行尾调用优化。我还没有寻找可能启用它的选项。如果有的话,我会感到惊讶。
在我们不会爆栈的情况下,递归成本如何?请参见我对 Bill Cheatham 的回答:看起来时间开销是相当大的,但不是疯狂的。
... 但是 Bill Cheatham 在我留下评论后删除了他的回答。好吧。因此,我对斐波那契函数进行了简单的迭代实现和简单的尾递归实现,在两者中都执行基本相同的计算,并在 fib(60)
上对它们进行了计时。递归实现的运行时间约为迭代实现的 2.5 倍。当然,对于执行比每次迭代一个加法和一个减法更多工作的函数,相对开销将更小。
(我也同意 delnan 的观点:在 Haskell 中感觉自然的高度递归代码通常不太符合 MATLAB 的惯用法。)