JavaScript

时间:2017-06-26 11:09:43

标签: javascript recursion

如果它是块(IIUC)中的最后一个表达式,JavaScript将仅优化为非递归循环的递归步骤。这是否意味着右手递归调用将被优化,左手递归调用将不会在下面?

function fibonacci(n) {
  if(n < 2) return n;
  return fibonacci(n-1) + fibonacci(n-2);
}

1 个答案:

答案 0 :(得分:3)

  

这是否意味着右手递归调用将被优化,左手递归调用将不会在下面?

我不这么认为。只有在您直接返回其他函数返回的内容时才可以使用TCO。由于您的函数在返回结果之前处理这两个结果,因此这两个调用都不能进行尾部优化。

低级别说明

就基于堆栈的机器而言,代码如下:

function fun1()
   return fun2(42)

function fun2(arg)
    return arg + 1

已翻译为此

fun1:
    push 42
    call fun2
    result = pop
    push result
    exit

fun2:
    arg = pop
    arg = arg + 1
    push arg
    exit

TCO可以消除call-pop-push,而是直接跳转到fun2

fun1:
    push 42
    goto fun2
    exit

然而,像你这样的代码片段就是这样:

fun1:
    push n - 1
    call fun2
    result1 = pop

    push n - 2
    call fun2
    result2 = pop

    result3 = result1 + result2
    push result3
    exit

此处,无法使用跳转替换调用,因为我们需要返回fun1来执行添加。

  

免责声明:这是一个相当理论上的解释,我不知道现代JS编译器如何实际实现TCO。他们非常聪明,所以也许有一种方法可以优化这样的东西。