Memoize a currified function

前端 未结 3 1686
别那么骄傲
别那么骄傲 2021-01-31 15:37
const f = (arg1) => (arg2) => { /* returns something */ }

Is it possible to memoize f with regard to the 2 arguments, namely:

f(1         


        
相关标签:
3条回答
  • 2021-01-31 16:16

    You could take a Map as cache and take nested maps for all following arguments.

    This cache works for arbitrary count of arguments and reuses the values from the former calls.

    It works by taking a curried function and an optional Map. If the map is not supplied, a new map is created which serves as base cache for all other calls of the returned closure or the final result.

    The inner function takes a single argument and checks if this value is in the map.

    • If not, call the curried function and check the returned value

      • if function, create a new closure over the function and a new map,

      • if no function take the result,

      as value for a new element of the map.

    • Finally return the value from the map.

    const cached = (fn, map = new Map()) => arg => {
        const inCache = map.has(arg);
        const hint = inCache ? 'in cache' : 'not in cache';
    
        console.log(arg, hint);
    
        if (!inCache) {
            const value = fn(arg);
            const result = typeof value === 'function' ? cached(value, new Map()) : value;
    
            map.set(arg, result);
        }
    
        return map.get(arg);
    };
    
    const f = a => b => c => a * b * c; // the original curried function
    const g = cached(f); // its cached variant
    
    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; }

    0 讨论(0)
  • 2021-01-31 16:17

    Interesting question — you could have independent caches for each function. The cache on the outside function will hold functions. Each inside function could get its own independent cache. So calling f(10)(1) followed by f(10)(2) would result in calling a cached version of the inside function. Calling f(10)(1) again would hit both caches:

    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))

    Another alternative would be to have single cache with keys that are a combination of both arguments, but then the inner function would always have to be called.

    0 讨论(0)
  • 2021-01-31 16:28

    You can not to pass map to every function. You can do like the next:

    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));
        }
      }
    }

    0 讨论(0)
提交回复
热议问题