我概括了 clojure 的 loop
/recur
蹦床,以便它可以与间接递归一起工作:
const trampoline = f => (...args) => {
let acc = f(...args);
while (acc && acc.type === recur) {
let [f, ...args_] = acc.args;
acc = f(...args_);
}
return acc;
};
const recur = (...args) =>
({type: recur, args});
const even = n =>
n === 0
? true
: recur(odd, n - 1);
const odd = n =>
n === 0
? false
: recur(even, n - 1);
console.log(
trampoline(even) (1e5 + 1)); // false
但是,我必须在调用方显式调用蹦床。有没有办法让它再次隐式化,就像 loop
/recur
一样?
顺便说一句,这里是loop
/recur
:
const loop = f => {
let acc = f();
while (acc && acc.type === recur)
acc = f(...acc.args);
return acc;
};
const recur = (...args) =>
({type: recur, args});
最佳答案
很明显,既然你想调用 trampolining,就不能完全跳过它。最简单的事情就是将那些蹦床调用包装在您想要的 API 中,也许是这样的:
// Utility code
const trampoline = f => (...args) => {
let acc = f(...args);
while (acc && acc.type === recur) {
let [f, ...args_] = acc.args;
acc = f(...args_);
}
return acc;
};
const recur = (...args) =>
({type: recur, args});
// Private implementation
const _even = n =>
n === 0
? true
: recur(_odd, n - 1);
const _odd = n =>
n === 0
? false
: recur(_even, n - 1);
// Public API
const even = trampoline(_even);
const odd = trampoline(_odd);
// Demo code
console.log(
even (1e5 + 1)); // false
console.log(
odd (1e5 + 1)); // true
关于javascript - 堆栈安全的相互递归,不会在调用端泄露实现细节,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55524078/