Reputation: 936
one argument——another function——and returns a "memoized" version of that function. A "memoized" version of a function caches and returns the results of its call so that when it is called again with the same input, it doesn’t run its computation but instead returns the results from cache. Note that previous results should be retrievable in any order without re-computation.
foo = function (x) {
console.log("calculating!");
return x + 5;
}
var memoizedFoo = memoize(foo);
memoizedFoo(5);
// calculating!
// 10
memoizedFoo(5);
// 10 (notice how 'calculating!' is not printed this time)
memoizedFoo(10);
// calculating!
// 15
Upvotes: 0
Views: 74
Reputation: 1074268
I assume the question is how to write memoize
. You can store the first result for a given argument in a container, and return a function that will use that container if it can.
Here's an ES5 example, which only works for argument values that can be usefully converted to strings, like strings, numbers, booleans:
function memoize(f) {
// Storage for this function's results
var values = Object.create(null);
return function(arg) {
// Already have it?
if (Object.hasOwnProperty.call(values, arg)) {
// Yes, return it
return values[arg];
}
// No, get it, remember it, and return it
return values[arg] = f(arg);
};
}
var foo = function (x) {
console.log("calculating!");
return x + 5;
};
var memoizedFoo = memoize(foo);
console.log(memoizedFoo(5));
// calculating!
// 10
console.log(memoizedFoo(5));
// 10
console.log(memoizedFoo(10));
// calculating!
// 15
If you need to support other kinds of arguments, you need to use another structure, or a Map
polyfill. Which brings us to...
...in ES2015+, we can use Map
, which makes it work with a broader range of argument values:
function memoize(f) {
// Storage for this function's results
const values = new Map();
return function(arg) {
// Already have it?
if (values.has(arg)) {
// Yes, return it
return values.get(arg);
}
// No, get it, remember it, and return it
const value = f(arg);
values.set(arg, value);
return value;
};
}
const foo = function (x) {
console.log("calculating!");
return x.foo + 5;
};
const memoizedFoo = memoize(foo);
const firstArg = {foo:5};
console.log(memoizedFoo(firstArg));
// calculating!
// 10
console.log(memoizedFoo(firstArg));
// 10
const secondArg = {foo:10};
console.log(memoizedFoo(secondArg));
// calculating!
// 15
// Note that maps consider equivalent but distinct objects as different (of course),
// so we don't get the memoized reslt from
// `firstArg` here
const thirdArg = {foo:5};
console.log(memoizedFoo(secondArg));
// calculating!
// 10
Upvotes: 2