Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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!

like image 607
tsaiDavid Avatar asked Sep 12 '15 20:09

tsaiDavid


People also ask

How do you memoize a function in react?

Using useMemo() useMemo() is a React hook that accepts a function and a dependency array. const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]); It memoizes the value returned from that function.

How do you memoize in Python?

To memoize a function in Python, we can use a utility supplied in Python's standard library—the functools. lru_cache decorator. Now, every time you run the decorated function, lru_cache will check for a cached result for the inputs provided. If the result is in the cache, lru_cache will return it.

How does Lodash memoize work?

Syntax. Creates a function that memoizes the result of func. If resolver is provided, it determines the cache key for storing the result based on the arguments provided to the memoized function. By default, the first argument provided to the memoized function is used as the map cache key.


1 Answers

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.

like image 185
dwickern Avatar answered Nov 01 '22 18:11

dwickern