如何将此大型因子函数转换为高阶函数?

时间:2017-04-10 13:08:57

标签: functional-programming factorial higher-order-functions

以下代码使用cache函数之外的factorial对象。 factorial函数本身很大,对寻找因子和缓存有太多关注。

如何将此代码转换为高阶函数,并在调用

时生成相同的结果
console.log(factorial(5));
console.log(factorial(7));



cache = { }

function factorial(n) {
  
  if (n === 0) {
    return 1;
  }
  
  if (cache[n])
  {
    return cache[n];
  }
  
  console.log("Stack Up: " + n);
  
  var value = n * factorial(n - 1);
  
  console.log("Stack Down: " + value);
  
  cache[n] = value;
  
  return value;
}

console.log(factorial(5));
console.log(factorial(7));




1 个答案:

答案 0 :(得分:1)

已经other answers out there for memoising recursive functions,但我会在javascript中将该答案调整为factorial,以便您可以更轻松地了解它的工作原理

编写memoised递归函数的秘诀是延续传递风格。当您想要使非尾递归函数成为堆栈安全时,类似的技术也可以工作。

我将在第一个示例中留下一些console.log语句,这样您就可以看到它实际计算的时间以及何时进行备忘录查找。

const memoise = f => {
  const memo = new Map()
  const compute = (x, k) =>
    (console.log('compute', x),
    memo.get(x, memo.set(x, f(x,k))))
  const lookup = x =>
    (console.log('lookup', x),
    memo.has(x) ? memo.get(x) : compute(x, lookup))
  return lookup
}

const factk = (x, k) => {
  if (x === 0)
    return 1
  else
    return x * k(x - 1)
}

const memfact = memoise(factk)

console.log(memfact(5)) // 120
console.log(memfact(7)) // 5040

在这里,我删除了console.log内的memoise次调用,而是演示了一个记忆的斐波那契函数与一个未记忆的函数。比较memoise(fibk)badfib

之间的戏剧性时差

const memoise = f => {
  const memo = new Map()
  const compute = (x, k) =>
    memo.get(x, memo.set(x, f(x,k)))
  const lookup = x =>
    memo.has(x) ? memo.get(x) : compute(x, lookup)
  return lookup
}

const fibk = (x, k) => {
  if (x < 2)
    return x
  else
    return k(x - 1) + k(x - 2)
}

const badfib = x => {
  if (x < 2)
    return x
  else
    return badfib(x - 1) + badfib(x - 2)
}

console.time('memoised')
console.log(memoise (fibk) (35)) // 9227465 1.46ms
console.timeEnd('memoised')

console.time('unmemoised')
console.log(badfib(35))          // 9227465 135.85ms
console.timeEnd('unmemoised')