javascript - 堆栈安全的相互递归,不会在调用端泄露实现细节

标签 javascript recursion tail-recursion mutual-recursion trampolines

我概括了 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/

相关文章:

javascript - 如何从输入中检索文本

Javascript 对象在 IE 中为 null 或不是对象

javascript - 如何更可靠地从动态变化的元素中获取变量?

java - Java中的递归方法似乎只是 "goto"方法的第一行,而不是实际进入下一个调用

Java递归趣味测试错误

javascript - 为什么我的 Protractor 测试用例中没有定义 webdriver?

algorithm - 关于T(n)的上下界

perl - 如何从目录树在 Perl 中构建层次哈希

c - 编写简单的 du clone。获取子目录中文件大小的随机值。

scala - 迭代过程的流与尾递归