所以我看到的尾部递归的常见示例之一是:
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)
}
}
我知道这行不通。我认为这仅仅是因为这不是真正的尾递归调用?还是会优化尾巴吗?
您的最后一个例子不是尾注,因为您必须继续呼叫factorial
之前,您可以呼叫multiply
。考虑:
阶乘(5)在获得阶乘(4)的结果之前不能调用乘法在获得阶乘(3)的结果之前不能调用乘法在获得阶乘(2)的结果之前不能调用乘法在获得阶乘(1)的结果之前不能调用乘法在有阶乘(0)的结果之前不能调用乘法
仅在这一点上您停止递归并调用multiply
。因此,没有尾声。
可能还值得注意的是,TCO几乎仅由Safari的JavaScriptCore实现。它不是由Chrome的V8或Firefox的SpiderMonkey实施的,也可能不是规范或没有规范。 :-)更多here和here。
我应该注意,您要求的标题是
为什么'+'不允许呢?
确实。 TCO不在乎操作是什么*
与+
,只是它位于尾部位置。