Skip to content

Instantly share code, notes, and snippets.

@joedski
Created July 15, 2017 03:49
Show Gist options
  • Save joedski/5b7bfc61d9f88b768ed49b374e46964b to your computer and use it in GitHub Desktop.
Save joedski/5b7bfc61d9f88b768ed49b374e46964b to your computer and use it in GitHub Desktop.
Tierd Memoization of Functions of Arbitrary Arites (also fixed the single memo)
// Simple naive single-param single-memo.
function singleMemo(fn) {
let calledAtLeastOnce = false;
let prevArg;
let value;
return function singleMemoizedFn(arg) {
if (arg !== prevArg || !calledAtLeastOnce) {
calledAtLeastOnce = true;
prevArg = arg;
value = fn(arg);
}
return value;
};
}
// Saves a function and args, deferring application with a thunk.
// The result is cached the first time and returned on subsequent calls.
function memoizeApplication(fn, args) {
let called = false;
let value;
return function thunk() {
if (!called) {
called = true;
value = fn(...args);
}
return value;
};
}
function createApplier(calculator, getMemoizerFor, args) {
const memoize = getMemoizerFor(args.length);
const cachedCalculate = memoizeApplication(calculator, args);
const memoizedApplyNextArg = memoize(function applyNextArg(arg) {
const nextArgs = [...args, arg];
return createApplier(calculator, getMemoizerFor, nextArgs);
});
return function applyArg() {
if (arguments.length) {
return memoizedApplyNextArg(arguments[0]);
}
else {
return cachedCalculate();
}
};
}
function createTieredMemoizer(options = {}) {
const {
memoizers = [],
defaultMemoizer = singleMemo,
} = options;
function getMemoizerFor(n) {
return memoizers[n] || defaultMemoizer;
}
return function tieredMemoize(calculator) {
const initApplyArg = createApplier(calculator, getMemoizerFor, []);
return function selector(...args) {
return args.reduce(
(applyArg, arg) => applyArg(arg),
initApplyArg
)(); // call the last one with no args.
};
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment