如何将这个大阶乘函数转换为高阶函数?
How can I convert this large factorial function to a higher-order function?
以下代码在 factorial
函数之外使用了一个 cache
对象。 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));
已经有 other answers out there for memoising recursive functions,但我会在 javascript 中将该答案调整为阶乘,以便您可以更轻松地了解它的工作原理
编写记忆递归函数的秘诀是延续传递风格。当您想使非尾递归函数堆栈安全时,可以使用类似的技术。
我将在第一个示例中留下一些 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
在这里,我删除了 memoise
内的 console.log
调用,而是演示了一个记忆的斐波那契函数与一个未记忆的斐波那契函数。比较 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')
以下代码在 factorial
函数之外使用了一个 cache
对象。 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));
已经有 other answers out there for memoising recursive functions,但我会在 javascript 中将该答案调整为阶乘,以便您可以更轻松地了解它的工作原理
编写记忆递归函数的秘诀是延续传递风格。当您想使非尾递归函数堆栈安全时,可以使用类似的技术。
我将在第一个示例中留下一些 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
在这里,我删除了 memoise
内的 console.log
调用,而是演示了一个记忆的斐波那契函数与一个未记忆的斐波那契函数。比较 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')