【问题标题】:Javascript change recursive function with trampoline version [duplicate]Javascript使用蹦床版本更改递归函数[重复]
【发布时间】:2017-12-24 06:48:00
【问题描述】:

如何更改以下代码以使用蹦床功能?谢谢。

var count = function (n) {
    if(typeof n !== 'number' || n % 1 !== 0) return null;
    if(n < 3) { return 1; }
    console.log(n)
    return count(n - 1) + count(n - 3)
}

【问题讨论】:

  • 什么是“蹦床功能”?
  • 你有没有尝试过?

标签: javascript functional-programming


【解决方案1】:

首先,我将count写成纯表达式

const count = (n) =>
  n < 3
    ? 1
    : count (n - 1)
      + count (n - 3)

// demo
for (let n = 0; n < 10; n = n + 1)
  console.log (n, count (n))

然后我将count 转换为继续传递样式

const count = (n, k = x => x) =>
  n < 3
    ? k (1)
    : count (n - 1, x =>
        count (n - 3, y =>
          k (x + y)))

// demo
for (let n = 0; n < 10; n = n + 1)
  console.log (n, count (n))

现在count 位于尾部位置,我们可以轻松地将其放在蹦床上——当然,您可以使用任何您想要的蹦床实现

const countLoop = (n, k = x => x) =>
  n < 3
    ? k (1)
    : bounce (countLoop, n - 1, x =>
        bounce (countLoop, n - 3, y =>
          k (x + y)))

const count = (n) =>
  trampoline (countLoop (n))

const trampoline = (acc) =>
  {
    while (acc && acc.tag === bounce)
      acc = acc.f (...acc.values)
    return acc
  }

const bounce = (f, ...values) =>
  ({ tag: bounce, f, values })

// demo
for (let n = 0; n < 10; n = n + 1)
  console.log (n, count (n))

或者我们可以使用 clojure 风格的循环/递归蹦床——我更喜欢这种风格,因为它需要一个辅助助手(即上面的 countLoop

const count = (m) =>
  loop ((n = m, k = x => x) =>
    n < 3
      ? k (1)
      : recur (n - 1, x =>
          recur (n - 3, y =>
            k (x + y))))

const loop = (f) =>
  {
    let acc = f ()
    while (acc && acc.tag === recur)
      acc = f (...acc.values)
    return acc
  }

const recur = (...values) =>
  ({ tag: recur, values })

// demo
for (let n = 0; n < 10; n = n + 1)
  console.log (n, count (n))

【讨论】:

  • 使用另一种称为memoization的技术可以显着提高此函数的速度
猜你喜欢
  • 2016-03-24
  • 2021-06-01
  • 1970-01-01
  • 2018-11-02
  • 1970-01-01
  • 2011-12-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多