javascript - 尾递归优化:为什么 '+' 不允许这样做?
问题描述
所以我看到的尾递归的一个常见例子是:
function factorial(x) {
if (x <= 0) {
return 1;
} else {
return x * factorial(x-1); // (A)
}
}
它针对 Tail 调用进行了优化:
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)
}
}
我知道这行不通。我认为这只是因为它不是真正的尾递归调用?不过,这仍然会进行尾部优化吗?
解决方案
您的最后一个示例不是尾随呼叫,因为您必须先继续呼叫factorial
,然后才能呼叫multiply
。考虑:
阶乘(5) 在得到阶乘(4)的结果之前不能调用乘法 在得到阶乘(3)的结果之前不能调用乘法 在得到阶乘(2)的结果之前不能调用乘法 在得到阶乘(1)的结果之前不能调用乘法 在得到阶乘(0)的结果之前不能调用乘法
只有在这一点上,您才停止递归并调用multiply
. 所以,没有尾声。
可能还值得注意的是,TCO 几乎仅由 Safari 的 JavaScriptCore 实现。它不是由 Chrome 的 V8 或 Firefox 的 SpiderMonkey 实现的,也不太可能是规范或没有规范。:-) 更多here和here。
我应该注意到,在你的标题中你问
为什么'+'不允许这样做?
确实如此。TCO 并不关心操作是什么——*
与+
——只是它处于尾部位置。
推荐阅读
- javascript - 在提交按钮附近显示引导表单验证
- android - Android 应用程序仅响应三星 SPen 悬停和触摸事件
- javascript - 无法触发 setState 对随后的数据提取做出反应,通过 papa 解析传递新的道具来重新渲染子组件?
- php - centos7 yum-complete-transaction 错误
- android - 屏幕关闭时不启动警报活动
- angular - 添加和不清除的验证器(ngx-chips,角度)
- javascript - module.exports = exports['default'] 是什么意思?
- r - 如何用R循环编写几个rasterStack
- javascript - 在 IOS 设备上否定 chrome 的正则表达式
- excel - 在邮件中插入与唯一 ID 关联的 Excel 数据