tsaiDavid
tsaiDavid

Reputation: 355

Implementing and understanding "memoize" function in underscore & lodash

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

Answers (1)

dwickern
dwickern

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

Related Questions