Created
July 15, 2017 03:49
-
-
Save joedski/5b7bfc61d9f88b768ed49b374e46964b to your computer and use it in GitHub Desktop.
Tierd Memoization of Functions of Arbitrary Arites (also fixed the single memo)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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