在JavaScript中为多个值实现备忘模式

时间:2019-04-16 15:40:27

标签: javascript memoization

我正在尝试发挥作用,并使用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

这里是多个键的版本,它不能按预期工作,它仅输出“ computing Array []”,“ computing undefined”:

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

这是怎么了?

1 个答案:

答案 0 :(得分:0)

您的代码有很多问题。首先,reducefold的一种,这意味着它通常用于将数据结构“折叠”为单个值。为此,传递给reduce的函数首先获取 accumulation 值,然后获取数据结构内的每个值。

const sumOf = ns => ns.reduce((sum, num) => sum + num, 0);

sumOf([1, 2, 3, 4, 5]); // -> 15

在此示例中,数据结构是Array,其中包含Number值。 reduce用于将数组中的所有数字折叠为最终值(通过求和)。折叠函数称为 reducer函数(在此示例中为加法运算)。最后,传递给reduce的0 seed 值。

让我们逐步跟踪发生的情况:

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

(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,但是reducer函数不会将中间结果作为新的累加器值返回,并且您不会返回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);

我希望这可以澄清一些事情。编码愉快!