Запоминать закриченную функцию - PullRequest
0 голосов
/ 07 января 2019
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

Ответы [ 2 ]

0 голосов
/ 07 января 2019

Вы можете взять Map в качестве кэша и использовать вложенные карты для всех следующих аргументов.

Этот кеш работает для произвольного числа аргументов и повторно использует значения из предыдущих вызовов.

Он работает с функцией карри и дополнительным Map. Если карта не указана, создается новая карта, которая служит базовым кэшем для всех других вызовов возвращаемого замыкания или конечного результата.

Внутренняя функция принимает один аргумент и проверяет, есть ли это значение на карте.

  • Если нет, вызовите функцию карри и проверьте возвращаемое значение

    • if function, создать новое замыкание над функцией и новую карту,

    • если функция не принимает результат,

    как значение для нового элемента карты.

  • Наконец, верните значение с карты.

const
    cache = (fn, map = new Map) => arg => {
        console.log(arg, map.has(arg) ? 'in cache' : 'not in cache');
        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; }
0 голосов
/ 07 января 2019

Интересный вопрос - вы можете иметь независимые кэши для каждой функции. Кэш на внешней функции будет содержать функции. Каждая внутренняя функция может получить свой независимый кеш. Таким образом, вызов 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))

Другой альтернативой может быть отдельный кеш с ключами, которые являются комбинацией обоих аргументов, но тогда всегда будет вызываться внутренняя функция.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...