gpt4 book ai didi

javascript - Node.js 尾调用优化 : possible or not?

转载 作者:IT老高 更新时间:2023-10-28 22:05:23 26 4
gpt4 key购买 nike

到目前为止,我喜欢 JavaScript,并决定使用 Node.js 作为我的引擎,部分原因是 this ,它声称 Node.js 提供 TCO。但是,当我尝试使用 Node.js 运行这个(显然是尾调用)代码时,它会导致堆栈溢出:

function foo(x) {
if (x == 1) {
return 1;
}
else {
return foo(x-1);
}
}

foo(100000);

现在,我进行了一些挖掘,发现了 this .这里,好像说我应该这样写:

function* foo(x) {
if (x == 1) {
return 1;
}
else {
yield foo(x-1);
}
}

foo(100000);

但是,这给了我语法错误。我尝试了它的各种排列方式,但在所有情况下,Node.js 似乎都对 something 不满意。

基本上,我想知道以下几点:

  1. Node.js 有没有 TCO?
  2. 这个神奇的 yield 东西在 Node.js 中是如何工作的?

最佳答案

这里有两个相当不同的问题:

  • Node.js 有没有 TCO?
  • 这个神奇的 yield 东西在 Node.js 中是如何工作的?

Does or doesn't Node.js do TCO?

TL;DR:不再,从 Node 8.x 开始。它在某个标志或另一个标志后面做了一段时间,但在撰写本文时(2017 年 11 月)它不再存在,因为它使用的底层 V8 JavaScript 引擎不再支持 TCO。见 this answer了解更多信息。

详情:

尾调用优化 (TCO) 是必需的 part of the ES2015 ("ES6") specification .所以直接支持它并不是 NodeJS 的事情,而是 NodeJS 使用的 V8 JavaScript 引擎需要支持的事情。

从 Node 8.x 开始,V8 不支持 TCO,甚至不支持标志。它可能会在未来的某个时候(再次)这样做;见 this answer了解更多信息。

Node 7.10 至少降到 6.5.0(我的笔记说 6.2,但 node.green 不同意)支持标志后面的 TCO(--harmony 在 6.6.0 及更高版本中, --harmony_tailcalls 之前)仅在严格模式下。

如果你想检查你的安装,这里是测试node.green用途(如果您使用的是相关版本,请务必使用该标志):

function direct() {
"use strict";
return (function f(n){
if (n <= 0) {
return "foo";
}
return f(n - 1);
}(1e6)) === "foo";
}

function mutual() {
"use strict";
function f(n){
if (n <= 0) {
return "foo";
}
return g(n - 1);
}
function g(n){
if (n <= 0) {
return "bar";
}
return f(n - 1);
}
return f(1e6) === "foo" && f(1e6+1) === "bar";
}

console.log(direct());
console.log(mutual());
$ # Only certain versions of Node, notably not 8.x or (currently) 9.x; see above$ node --harmony tco.jstruetrue

How does this magical yield thing work in Node.js?

This is another ES2015 thing ("generator functions"), so again it's something that V8 has to implement. It's completely implemented in the version of V8 in Node 6.6.0 (and has been for several versions) and isn't behind any flags.

Generator functions (ones written with function* and using yield) work by being able to stop and return an iterator that captures their state and can be used to continue their state on a subsequent occasion. Alex Rauschmeyer has an in-depth article on them here.

Here's an example of using the iterator returned by the generator function explicitly, but you usually won't do that and we'll see why in a moment:

"use strict";
function* counter(from, to) {
let n = from;
do {
yield n;
}
while (++n < to);
}

let it = counter(0, 5);
for (let state = it.next(); !state.done; state = it.next()) {
console.log(state.value);
}

有这个输出:

01234

Here's how that works:

  • When we call counter (let it = counter(0, 5);), the initial internal state of the call to counter is initialized and we immediately get back an iterator; none of the actual code in counter runs (yet).
  • Calling it.next() runs the code in counter up through the first yield statement. At that point, counter pauses and stores its internal state. it.next() returns a state object with a done flag and a value. If the done flag is false, the value is the value yielded by the yield statement.
  • Each call to it.next() advances the state inside counter to the next yield.
  • When a call to it.next() makes counter finish and return, the state object we get back has done set to true and value set to the return value of counter.

Having variables for the iterator and the state object and making calls to it.next() and accessing the done and value properties is all boilerplate that (usually) gets in the way of what we're trying to do, so ES2015 provides the new for-of statement that tucks it all away for us and just gives us each value. Here's that same code above written with for-of:

"use strict";
function* counter(from, to) {
let n = from;
do {
yield n;
}
while (++n < to);
}

for (let v of counter(0, 5)) {
console.log(v);
}

v 对应于我们之前示例中的 state.valuefor-of 完成所有 it.next() 调用和 done 为我们检查。

关于javascript - Node.js 尾调用优化 : possible or not?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23260390/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com