Adi*_*ngh 51 javascript recursion tail-recursion
我一直试图Tail call optimization在JavaScript的上下文中理解并编写了下面的递归和尾递归方法factorial().
递归:
function factorial (n) {
if (n < 2) {
return 1;
} else {
return n * factorial(n-1);
}
}
Run Code Online (Sandbox Code Playgroud)
尾递归:
function factorial (n) {
function fact(n, acc) {
if (n < 2) {
return acc;
} else {
return fact(n-1, n * acc);
}
}
return fact(n, 1)
}
Run Code Online (Sandbox Code Playgroud)
但我不确定tail-recursive该函数的版本是否会被JavaScript编译器优化,因为它是在Scala等其他语言中完成的.有人可以帮我解决这个问题吗?
she*_*tme 36
更新:截至2018年3月13日,Safari是唯一支持尾部呼叫优化的浏览器.
铬团队明确指出Tail Call Optimization未进行积极开发,可在此处进行跟踪.
可以在此处跟踪Firefox的实现
原帖
是的,ES2015在严格模式下提供尾调用优化.Axel Rauschmayer博士在下面的链接中精美地展示了它,所以我不会在这里重复他的话.
注意:ES 5不优化尾调用.
http://www.2ality.com/2015/06/tail-call-optimization.html
tjj*_*fvi 10
正如其他答案所说,实际上并非如此。但是,您可以定义一个实用程序来提供帮助。
class Tco {
constructor(func) {
this.func = func;
}
execute() {
let value = this;
while (value instanceof Tco)
value = value.func();
return value;
}
}
const tco = (f) => new Tco(f);
Run Code Online (Sandbox Code Playgroud)
function factorial (n) {
const fact = (n, acc) => tco(() => {
if (n < 2) {
return acc;
} else {
return fact(n-1, n * acc);
}
});
return fact(n, 1).execute();
}
console.log(factorial(2000000)); // Infinity
Run Code Online (Sandbox Code Playgroud)
如您所见,这允许您编写仅在语法上有很小差异的尾递归函数,而不会遇到最大调用堆栈错误。