2

以下代码使用factorial函数之外的cache对象。函数本身很大,对寻找阶乘和缓存有太多顾虑。如何将此大因子函数转换为更高阶的函数?

我怎么能这样的代码转换为高阶函数并产生相同的结果时,我打电话

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

这样的高阶函数通常被称为* memoize的* /记忆化是Google保持着良好的关键字的巨大时间差。 – stholzm

+1

看看[这些例子](http://stackoverflow.com/a/22578970/1048572) – Bergi

回答

1

有已经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


在这里,我已经删除的memoiseconsole.log电话,而是表现出memoised斐波那契功能VS的unmemoised之一。比较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')

+1

我们可以进一步使用部分应用程序 - 'fibk = k => x => ...' – Bergi

+0

我不是看看部分应用程序在这个时候会有所帮助...请给我看!^_^ – naomik

+0

也许这并没有多大帮助,但'const lookup = x =>(memo.has(x)?memo:memo.set(x,comp(x)))。get(x); const comp = f(lookup);' – Bergi