在 JavaScript 中实现多个值的记忆模式



我正在尝试玩一点并使用JavaScript为多个值实现记忆模式。 我设法为单个值编写了代码:

var lazy = {};
lazy.memoization = evaluator => {
const cache = new Map;
return key => {
cache.has(key) || cache.set(key, evaluator(key));
return cache.get(key);
};
};
var memoize = lazy.memoization(key => console.log('computing ', key));
memoize(1); // -> computing 1
memoize(2); // -> computing 2

这是多个键的版本,它没有按预期工作,它只是输出"计算数组 []"、"计算未定义":

var lazy = {};
lazy.memoization = evaluator => {
const cash = new Map;
return (...keys) => {
var values = [];
keys.reduce((v, f) => {
if (!cash.has(v)) {
cash.set(v, evaluator(v));
}
values.push(cash.get(v));
}, values);
return values;
};
};
var memoizeMultiple = lazy.memoization((...keys) => {
keys.forEach(key => console.log('computing ', key))
});
memoizeMultiple(1, 2);

这是怎么回事?

你的代码有很多问题。首先,reduce是一种fold,这意味着它通常用于将数据结构"折叠"为单个值。为此,传递给reduce的函数首先获取累积值,然后获取数据结构中的每个值。

const sumOf = ns => ns.reduce((sum, num) => sum + num, 0);
sumOf([1, 2, 3, 4, 5]); // -> 15

在此示例中,数据结构是一个Array,其中包含Number值。reduce用于将数组中的所有数字折叠为最终值(通过将它们相加)。折叠函数称为化简函数(在本例中为加法)。最后,传递到reduce的0种子值。

让我们一步一步地追踪会发生什么:

在第一次迭代中,化简器函数传递种子值和数组中的第一个数字。因此,它看起来像:

(0, 1) => 0 + 1

第二次迭代从第一次迭代的结果开始,作为累加器值和数组中的第二个数字:

(1, 2) => 1 + 2

所以完整地,它的工作原理是这样的:

(0, 1) => 0 + 1
(1, 2) => 1 + 2
(3, 3) => 3 + 3
(6, 4) => 6 + 4
(10, 5) => 10 + 5

在最后一次迭代之后,reduce返回最终累加器,在本例中15

好的,回到你提供的代码。您的"多参数记忆"版本使用reduce,但化简器函数不会将中间结果作为新的累加器值返回,并且您不会返回reduce生成的最终结果。

另一个问题是您的evaluator功能。它返回的值存储在缓存Map实例中。在您的代码中,它不返回除undefined以外的任何内容。因此,undefined被存储并在随后调用记忆函数时返回。

如果我们解决这些问题,它就会起作用:

var lazy = {};
lazy.memoization = evaluator => {
const cache = new Map();
return (...args) => {
return args.reduce((acc, arg) => {
if (!cache.has(arg)) {
cache.set(arg, evaluator(arg)); // stores the returned value inside the cache variable
}
return acc.concat(cache.get(arg));
}, []); // the result should be an array, so use that as the seed
};
};
var memoizeMultiple = lazy.memoization(value => {
console.log('computing ', value)
return value; // you have to return something in here, because the return value is stored
});
memoizeMultiple(1, 2);

我希望这能澄清一些事情。祝您编码愉快!

最新更新