gpt4 book ai didi

javascript - NodeJS 中的尾递归

转载 作者:搜寻专家 更新时间:2023-10-31 22:58:11 24 4
gpt4 key购买 nike

所以我最近遇到了一个案例,我需要编写回调调用自身的代码等等,并且想知道 NodeJS 和尾调用支持,所以我找到了这个答案 https://stackoverflow.com/a/30369729是的,它受支持。

所以我用这个简单的代码试了一下:

"use strict";
function fac(n){
if(n==1){
console.trace();
return 1;
}
return n*fac(n-1);
}

fac(5);

在 Linux x64 上使用 Node 6.9.2 并将其作为 node tailcall.js --harmony --harmony_tailcalls --use-strict 运行结果是:

Trace
at fac (/home/tailcall.js:4:11)
at fac (/home/tailcall.js:7:11)
at fac (/home/tailcall.js:7:11)
at fac (/home/tailcall.js:7:11)
at fac (/home/tailcall.js:7:11)
at Object.<anonymous> (/home/tailcall.js:10:1)
at Module._compile (module.js:570:32)
at Object.Module._extensions..js (module.js:579:10)
at Module.load (module.js:487:32)
at tryModuleLoad (module.js:446:12)

虽然我使用最新的 NodeJS,但它清楚地表明调用堆栈充满了调用并且不支持尾递归。

NodeJS/JavaScript 是否完全支持尾递归?或者我真的必须使用生成器和 yield ,但这里的问题是我的回调将是高度异步的,无论如何我都不会使用返回值,我只需要确保调用堆栈不会无用地填充函数在返回时引用自身时调用。

最佳答案

你所拥有的不是尾声。尾调用是作为另一个函数的最终操作执行的函数调用。除了函数调用自身外,尾递归调用是相同的。

但是,您的代码的最终操作是n*fac(n-1),而不是fac(n-1)。这不是递归尾调用,因为当前堆栈在计算递归调用时仍需要记住 n,以便它知道要乘以哪些数字。

您可以做的是在 1 步之前计算此信息:

const fac = (n, result = 1) =>
n === 1
? result
: fac(n - 1, n * result);

console.log(fac(5)); // 120

或者根据您的代码:

function fac(n, result = 1) {
// base case
if (n === 1) {
return result;
}

// compute the next result in the current stack frame
const next = n * result;

// propagate this result through tail-recursive calls
return fac(n - 1, next);
}

这是来自 Chrome Canary 的堆栈跟踪:

Proper Tail Calls in Chrome Canary

关于javascript - NodeJS 中的尾递归,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41666751/

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