【问题标题】:Tail Recursion Optimization: Why does '+' not allow that?尾递归优化:为什么 '+' 不允许这样做?
【发布时间】:2020-05-01 17:00:33
【问题描述】:

所以我看到的尾递归的一个常见例子是:

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)
    }
}

我知道这行不通。我认为这只是因为它不是真正的尾递归调用?但这仍然会进行尾部优化吗?

【问题讨论】:

  • 您的示例中的 multiply 是什么?
  • 几乎所有地方仍然不支持 TCO。
  • @Grant Everett:请更改您的标题,我很乐意“支持”您的问题。请“投票”和“接受”T.J.如果它回答了您的问题,Crowder 的最出色的回答。
  • 我刚开始在这里提问。我只是将其更改为“已解决”吗?

标签: javascript recursion tail-recursion


【解决方案1】:

您的最后一个示例不是尾随呼叫,因为您必须继续呼叫factorial您可以呼叫multiply。考虑:

阶乘(5) 在得到阶乘(4)的结果之前不能调用乘法 在得到阶乘(3)的结果之前不能调用乘法 在得到阶乘(2)的结果之前不能调用乘法 在得到阶乘(1)的结果之前不能调用乘法 在得到阶乘(0)的结果之前不能调用乘法

此时您才停止递归并调用multiply。所以,没有尾声。

可能还值得注意的是,TCO 几乎仅由 Safari 的 JavaScriptCore 实现。它不是由 Chrome 的 V8 或 Firefox 的 SpiderMonkey 实现的,也不太可能是规范或没有规范。 :-) 更多 herehere

我应该注意到你在标题中问的问题

为什么 '+' 不允许这样做?

确实如此。 TCO 并不关心操作是什么——*+——只是它处于尾部位置。

【讨论】:

  • 非常感谢!这真的很有帮助:)
猜你喜欢
  • 1970-01-01
  • 2011-08-17
  • 2013-09-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-14
  • 2020-06-13
  • 2011-01-25
相关资源
最近更新 更多