Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Memoize a curried function

const f = (arg1) => (arg2) => { /* returns something */ } 

Is it possible to memoize f with regard to the 2 arguments, namely:

f(1)(2); f(1)(3); // Cache not hit f(4)(2); // Cache not hit f(1)(2); // Cache hit 
like image 825
jeanpaul62 Avatar asked Jan 07 '19 15:01

jeanpaul62


People also ask

What does it mean to Memoize a function?

In programming, memoization is an optimization technique that makes applications more efficient and hence faster. It does this by storing computation results in cache, and retrieving that same information from the cache the next time it's needed instead of computing it again.

How do you use Memoize function?

Importance of Memoization: When a function is given in input, it performs the necessary computation and saves the result in a cache before returning the value. If the same input is received again in the future, it will not be necessary to repeat the process. It would simply return the cached answer from the memory.

Can every function be Memoized?

Although it might look like memoization can be used with all functions, it actually has limited use cases: In order to memoize a function, it should be pure so that return values are the same for same inputs every time.

What is currying and how does it apply to a react application?

Currying is a function that takes one argument at a time and returns a new function expecting the next argument. It is a transformation of functions that translates a function from callable as f(a, b, c) into callable as f(a)(b)(c).


1 Answers

You could take a Map as cache and take nested maps for all following arguments.

This cache works for arbitrary count of arguments and reuses the values from the former calls.

It works by taking a curried function and an optional Map. If the map is not supplied, a new map is created which serves as base cache for all other calls of the returned closure or the final result.

The inner function takes a single argument and checks if this value is in the map.

  • If not, call the curried function and check the returned value

    • if function, create a new closure over the function and a new map,

    • if no function take the result,

    as value for a new element of the map.

  • Finally return the value from the map.

const cached = (fn, map = new Map()) => arg => {      const inCache = map.has(arg);      const hint = inCache ? 'in cache' : 'not in cache';        console.log(arg, hint);        if (!inCache) {          const value = fn(arg);          const result = typeof value === 'function' ? cached(value, new Map()) : value;            map.set(arg, result);      }        return map.get(arg);  };    const f = a => b => c => a * b * c; // the original curried function  const g = cached(f); // its cached variant    console.log(g(1)(2)(5)); // not not not 10  console.log(g(1)(3)(4)); //  in not not 12  console.log(g(4)(2)(3)); // not not not 24  console.log(g(1)(2)(6)); //  in  in not 12  console.log(g(4)(2)(3)); //  in  in  in 24
.as-console-wrapper { max-height: 100% !important; top: 0; }
like image 99
Nina Scholz Avatar answered Sep 23 '22 10:09

Nina Scholz