以下代码使用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));

答案 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')