记忆一个粗略的函数

时间:2019-01-07 15:25:31

标签: javascript caching memoization currying

const f = (arg1) => (arg2) => { /* returns something */ }

是否可以针对两个参数来记忆f,即:

f(1)(2);
f(1)(3); // Cache not hit
f(4)(2); // Cache not hit
f(1)(2); // Cache hit

3 个答案:

答案 0 :(得分:20)

您可以将Map用作缓存,并为以下所有参数获取嵌套映射。

此缓存可用于任意数量的参数,并可重用以前调用中的值。

它通过使用curried函数和可选的Map来工作。如果未提供该映射,则将创建一个新的映射,该映射将用作返回的闭包或最终结果的其他调用的基本缓存。

内部函数采用单个参数,并检查此值是否在映射中。

  • 如果没有,请调用curried函数并检查返回的值

    • 如果是函数,请在函数和新映射上创建一个新的闭包,

    • 如果没有函数接受结果,

    作为地图新元素的值。

  • 最后从地图返回值。

const
    cache = (fn, map = new Map) => arg => {
        console.log(arg, map.has(arg) ? 'in chache' : 'not in chache');
        if (!map.has(arg)) {
            var value = fn(arg);
            map.set(arg, typeof value === 'function' ? cache(value, new Map) : value);
        }
        return map.get(arg);
    },        
    f = a => b => c => a * b * c, // curried function
    g = cache(f);                 // cache function f, return function with closure

console.log(g(1)(2)(5)); // not not not 10
console.log(g(1)(3)(4)); //  in not not 12
console.log(g(4)(2)(3)); // not not not 24
console.log(g(1)(2)(6)); //  in  in not 12
console.log(g(4)(2)(3)); //  in  in  in 24
.as-console-wrapper { max-height: 100% !important; top: 0; }

答案 1 :(得分:2)

有趣的问题-每个功能可以具有独立的缓存。外部函数的缓存将保留函数。每个内部函数都可以获取自己的独立缓存。因此,调用f(10)(1)后跟f(10)(2)将导致调用内部函数的缓存版本。再次调用f(10)(1)将同时访问两个缓存:

function getCachedF() {
  // outer cache holds functions keyed to argument
  let outer_memo = {}  
                
  const f = (arg1) => {
    if (!outer_memo.hasOwnProperty(arg1)) {
      // Create inner function on outer cache
      // each inner function needs its own cache
      // because it will return different values
      // given different outer function calls
      let inner_memo = {}                  
      console.log("outer cache miss")
      
      outer_memo[arg1] = (arg2) => {
        // just a normal memoized function
        // cache is simple key:value pair
        if (!inner_memo.hasOwnProperty(arg2)) {
          console.log("inner cache miss")
          inner_memo[arg2] = arg1 + arg2
        }
        return inner_memo[arg2]
      }
    }
    return outer_memo[arg1]
  }
  return f
}

let f = getCachedF()
// both caches miss
console.log("3+5", f(3)(5))

// cached result
console.log("3+5", f(3)(5))

// only inside cache hit
console.log("3+8", f(3)(8))

// inside cache only hits if both args are the same
console.log("10+8", f(10)(8))

另一种选择是使用具有两个参数组合的键的单个缓存,但是内部函数始终必须被调用。

答案 2 :(得分:0)

您不能将映射传递给每个功能。 您可以像下一个一样做:

const memoize = fn => {
  const cache = {};
  return (...args) => {
    const curriedFn = fn(...args);
    return (...next) => {
      const key = // generate your key
      if (key in cache) return cache[key];
      return (cache[key] = curriedFn(...next));
    }
  }
}