阶乘尾调用的连续式实现是否优化(TCO)?
Is continuation style implementation of factorial tail call optimized (TCO)?
这里有两个阶乘实现from this site:
尾调用优化 (TCO):
function fact(n) {
return tail_fact(n,1) ;
}
function tail_fact(n,a) {
if (n == 0)
return a ;
else
return tail_fact(n-1,n*a) ;
}
以及在连续风格编程(回调)中重写的那个:
function fact(n,ret) {
tail_fact(n,1,ret) ;
}
function tail_fact(n,a,ret) {
if (n == 0)
ret(a) ;
else
tail_fact(n-1,n*a,ret) ;
}
似乎教程建议第二个也是TCO,但是第二个版本returns的最后一件事是undefined
,根据[=15,它的调用不在尾部位置=].
然而,这里似乎根本没有使用 return
,因此无需在堆栈上创建一个地址为 return 的新帧。这就是第二次实施 TCO 的原因吗?
具有 --harmony_tailcalls
的 Node7 不认为第二个对 TCO 有效,但 TCO 在 V8 中并非 100% 完成(因此落后于运行时标志)。
Axel Rauschmayer says no, it's not a tail call,因为有一个隐含的 return undefined
;在它之后:
The function call bar()
in the following code is not in tail position:
function foo() {
bar(); // this is not a tail call in JS
}
The reason is that the last action of foo()
is not the function call bar()
, it is (implicitly) returning undefined
. In other words, foo()
behaves like this:
function foo() {
bar();
return undefined;
}
Callers can rely on foo()
always returning undefined
. If bar()
were to return a result for foo()
, due to tail call optimization, then that would change foo’s behavior.
所以换句话说,在foo
的末尾,我们不能直接跳转到bar
,因为bar
可能会发出一个return
带有一个值除了 undefined
,而 foo
根本没有 return 任何值(因此调用它保证产生 undefined
)。 当我们打电话给 bar
说“但不要 return bar
的 return 值。”那是一个堆栈框架。
理论上,JavaScript引擎在调用bar
时可以传递某种标志告诉自己丢弃任何值bar
returns,因此在这种情况下允许 TCO,但我在规范中没有看到任何这样做的内容。
这里有两个阶乘实现from this site:
尾调用优化 (TCO):
function fact(n) {
return tail_fact(n,1) ;
}
function tail_fact(n,a) {
if (n == 0)
return a ;
else
return tail_fact(n-1,n*a) ;
}
以及在连续风格编程(回调)中重写的那个:
function fact(n,ret) {
tail_fact(n,1,ret) ;
}
function tail_fact(n,a,ret) {
if (n == 0)
ret(a) ;
else
tail_fact(n-1,n*a,ret) ;
}
似乎教程建议第二个也是TCO,但是第二个版本returns的最后一件事是undefined
,根据[=15,它的调用不在尾部位置=].
然而,这里似乎根本没有使用 return
,因此无需在堆栈上创建一个地址为 return 的新帧。这就是第二次实施 TCO 的原因吗?
具有 --harmony_tailcalls
的 Node7 不认为第二个对 TCO 有效,但 TCO 在 V8 中并非 100% 完成(因此落后于运行时标志)。
Axel Rauschmayer says no, it's not a tail call,因为有一个隐含的 return undefined
;在它之后:
The function call
bar()
in the following code is not in tail position:function foo() { bar(); // this is not a tail call in JS }
The reason is that the last action of
foo()
is not the function callbar()
, it is (implicitly) returningundefined
. In other words,foo()
behaves like this:function foo() { bar(); return undefined; }
Callers can rely on
foo()
always returningundefined
. Ifbar()
were to return a result forfoo()
, due to tail call optimization, then that would change foo’s behavior.
所以换句话说,在foo
的末尾,我们不能直接跳转到bar
,因为bar
可能会发出一个return
带有一个值除了 undefined
,而 foo
根本没有 return 任何值(因此调用它保证产生 undefined
)。 当我们打电话给 bar
说“但不要 return bar
的 return 值。”那是一个堆栈框架。
理论上,JavaScript引擎在调用bar
时可以传递某种标志告诉自己丢弃任何值bar
returns,因此在这种情况下允许 TCO,但我在规范中没有看到任何这样做的内容。