2.0.1 • Published 3 years ago

memoize-recursive v2.0.1

Weekly downloads
2
License
ISC
Repository
github
Last release
3 years ago

npm

Problem

Given a binary exponentiation function:

const exponent = (x, n) => {
  if (n === 0) {
    return 1;
  }
  if (n % 2 === 1) {
    return x * exponent(x * x, Math.floor(n / 2));
  } else {
    return exponent(x * x, Math.floor(n / 2));
  }
}

exponent(2, 8)
  // 256, three multiplications
exponent(2, 9)
  // 512, four multiplications

Consider given standart memoize function:

const mExponent = memoize(exponent)

mExponent(2, 8)
  // 256, three multiplications
mExponent(2, 8)
  // 256, returns the memoized result, no multiplications

mExponent(2, 9)
  // 512, four multiplications

The problem is that inner recursive call in exponent is not memoized

Workaround(hardcoced, not composable):

const mExponent = memoized((x, n) => {
  if (n === 0) {
    return 1;
  }
  if (n % 2 === 1) {
    return x * mExponent(x * x, Math.floor(n / 2));
  } else {
    return mExponent(x * x, Math.floor(n / 2));
  }
});

mExponent(2, 8)
  // 256, three multiplications
mExponent(2, 9)
  // 512, one multiplication

Solution

Define recursive function with abstraction point at f:

const exponent1 = (f) => (x, n) => {
  if (n === 0) {
    return 1;
  }
  if (n % 2 === 1) {
    return x * f(x * x, Math.floor(n / 2));
  } else {
    return f(x * x, Math.floor(n / 2));
  }
}

Create recursive function:

const {recursive} = require('memoize-recursive');

const exponent = recursive(exponent1);

exponent(2, 8)
  // 256, three multiplications
exponent(2, 8)
  // 256, three multiplications

Create recursive memoized function:

const {recursive, memoizeInner} = require('memoize-recursive');

const mExponent = recursive(memoizeInner(exponent1));

mExponent(2, 8)
  // 256, three multiplications
mExponent(2, 9)
  // 512, one multiplication