gpt4 book ai didi

javascript - 如何让 TypeScript 执行尾递归优化?

转载 作者:行者123 更新时间:2023-12-05 01:51:54 24 4
gpt4 key购买 nike

const isPositive = (n: number) => n > 0;

function fitsIn(dividend: number,
divisor: number,
count: number,
accum: number): number {
if (accum + divisor > dividend) {
return count;
}
return fitsIn(dividend, divisor, count + 1, accum + divisor);
}

function divide(dividend: number, divisor: number): number {
let timesFits = fitsIn(Math.abs(dividend), Math.abs(divisor), 0, 0);
return isPositive(dividend) === isPositive(divisor) ? timesFits : -timesFits;
}

console.log(divide(10, 3));
// 3

console.log(divide(-2147483648, -1));
// RangeError: Maximum call stack size exceeded

console.log(divide(10000, 1));
// RangeError: Maximum call stack size exceeded

我尝试在严格模式下使用 TypeScript 4.6.2 运行这段代码,它导致堆栈溢出。递归调用在函数的末尾,累加在递归函数调用内部完成。这段代码不应该针对尾递归进行优化吗?应该更改什么才能进行尾递归优化?

最佳答案

TypeScript 不会优化尾调用递归函数。参见 microsoft/TypeScript#32743求权威解答。

通常,JavaScript 中的术语“尾调用优化”表示将尾递归函数重写为迭代版本。这与“尾调用消除”有些不同,后者通常意味着保留递归但重写当前堆栈帧而不是将新堆栈帧压入堆栈。如果您只关心堆栈增长,那么从外部看两者的行为相似,但尾调用优化通常发生在比尾调用消除更高的抽象级别。


如果您建议 TypeScript 实现尾调用优化作为性能改进,那不适合 TypeScript's design goals .一般来说,如果您为目标运行时环境编写了一些语法正确的 JavaScript 代码,编译器将按原样发出该代码。 TypeScript 不应该优化你的 JavaScript,只是发出它。所以它不可能自己做这件事。


另一方面,您可能正在谈论 ECMAScript 2015 (ES2015/ES6) 规范中引入的适当的尾调用消除。此功能旨在让 JavaScript 运行时引擎检测尾部调用,并且在这种情况下不会添加到调用堆栈。

此功能从未被广泛采用; currently只有基于 Safari 的浏览器似乎一直这样做。

当运行时引擎设计人员考虑实现这一点时,他们遇到了可能的性能下降、开发人员混淆等问题。参见 this V8 blog post例如。大多数运行时引擎似乎都选择了一种“观望”的方法来获得一些更理想的版本,例如明确选择加入这种消除的语法。而唯一的notable proposal for such syntax多年来一直“不活跃”。所以看起来“观望”中的“等待”部分可能会永远持续下去。

虽然 TypeScript 可以将 downlevel适当的尾调用消除到尾调用优化之类的东西,它可能会遇到同样的问题,他们拒绝这样做。


不管是好是坏,自动尾调用消除似乎是一个事实上的死功能,TypeScript 不会为我们复活它。

关于javascript - 如何让 TypeScript 执行尾递归优化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71909776/

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