Reputation: 355
Have been trying to learn more about functional programming by looking at the underscore documentation and attempting to write my own versions of the more frequently used functions.
Coming across "memoize" - I was having trouble wrapping my head around it, and found some information in Crockford's 'The Good Parts'.
_.memoize = function(func) {
// 'cache' object is used to hold the result of the memoized fn's call
var cache = {};
var recur = function(n) {
var result = cache[n];
if (typeof result === 'undefined') {
result = func.apply(this, arguments);
cache[n] = result;
}
return result;
}
return recur;
};
Could you please help me understand if my use of .apply was even necessary and if there is any core improvement I can make to this code? Really appreciate the help!
Upvotes: 5
Views: 7114
Reputation: 3519
There are some obvious issues with correctness:
1) You cache the result based only on the value of the first argument, so calling a function with different arguments will produce a wrong result!
let add = memoize((a, b) => a + b)
add(1, 2)
> 3
add(1, 3)
> 3
2) You use undefined
to represent a function which has not been called yet, but undefined
is a valid return value. See how the side effect happens twice:
let log = memoize(() => console.log('hello'))
log()
> hello
log()
> hello
You can instead use cache.hasOwnProperty
to detect if something is in the cache.
I'd recommend for you to write a test suite. Tests are quite valuable in finding these bugs. Think up other edge cases where your function might not work properly. Standalone utilities like this really lend themselves to test-driven coding.
Upvotes: 7