const f = (arg1) => (arg2) => { /* returns something */ }
Можно ли запомнить f относительно 2 аргументов, а именно:
f(1)(2);
f(1)(3); // Cache not hit
f(4)(2); // Cache not hit
f(1)(2); // Cache hit
const f = (arg1) => (arg2) => { /* returns something */ }
Можно ли запомнить f относительно 2 аргументов, а именно:
f(1)(2);
f(1)(3); // Cache not hit
f(4)(2); // Cache not hit
f(1)(2); // Cache hit
Вы можете взять Map
качестве кэша и использовать вложенные карты для всех следующих аргументов.
Этот кеш работает для произвольного количества аргументов и повторно использует значения из предыдущих вызовов.
Это работает, беря карри функцию и опциональную Map
. Если карта не указана, создается новая карта, которая служит базовым кэшем для всех других вызовов возвращаемого замыкания или конечного результата.
Внутренняя функция принимает один аргумент и проверяет, есть ли это значение на карте.
Если нет, вызовите карри функцию и проверьте возвращаемое значение
если функция, создайте новое замыкание над функцией и новую карту,
если функция не принимает результат,
в качестве значения для нового элемента карты.
Наконец, верните значение с карты.
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; }
Интересный вопрос - вы можете иметь независимые кэши для каждой функции. Кэш на внешней функции будет содержать функции. Каждая внутренняя функция может получить свой независимый кеш. Таким образом, вызов 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))