尾递归优化:为什么'+'不允许这样做?

时间:2020-01-14 22:37:06

标签: javascript recursion tail-recursion

所以我看到的尾部递归的常见示例之一是:

function factorial(x) {
    if (x <= 0) {
        return 1;
    } else {
        return x * factorial(x-1); // (A)
    }
}

针对尾部通话进行了优化:

function factorial(n) {
    return facRec(n, 1);
}
function facRec(x, acc) {
    if (x <= 1) {
        return acc;
    } else {
        return facRec(x-1, x*acc); // (A)
    }
}

我明白了。但是我的问题是:为什么*在这种情况下不能优化? 我不能将顶部重写为

function factorial(x) {
    if (x <= 0) {
        return 1;
    } else {
        return multiply(x, factorial(x-1)); // (A)
    }
}

我知道这行不通。我认为这仅仅是因为这不是真正的尾递归调用?还是会优化尾巴吗?

1 个答案:

答案 0 :(得分:8)

您的最后一个例子不是尾部呼叫,因为您必须继续呼叫factorial,然后才能继续致电{strong> 。考虑:

factorial(5)
  can't call multiply until it has the result from factorial(4)
    can't call multiply until it has the result from factorial(3)
      can't call multiply until it has the result from factorial(2)
        can't call multiply until it has the result from factorial(1)
          can't call multiply until it has the result from factorial(0)

仅在这一点上您停止递归并调用multiply。因此,没有尾声。

也许还应该指出,TCO几乎仅由Safari的JavaScriptCore实现。它不是由Chrome的V8或Firefox的SpiderMonkey实施的,也可能不是规范或没有规范。 :-)更多herehere

我应该注意,在您的标题中您会问

为什么'+'不允许?

是的。 TCO不在乎操作是multiply*,只是在尾部。