Created
July 16, 2017 23:35
-
-
Save joedski/ddc97104551d28720c9fed5ed01cc9a7 to your computer and use it in GitHub Desktop.
The simplest case, which doesn't allow you to use existing memoizers, though you can use their stores if they expose that.
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 single-value store. | |
// Setting a KV pair overwrites the last. | |
// Follows a get/set/has interface similar to Maps. | |
function singleValueStore() { | |
let key; | |
let value; | |
let isSet = false; | |
function get(givenKey) { | |
if (!isSet) return undefined; | |
if (givenKey === key) return value; | |
return undefined; | |
} | |
function set(givenKey, givenValue) { | |
isSet = true; | |
key = givenKey; | |
value = givenValue; | |
} | |
function has(givenKey) { | |
if (!isSet) return false; | |
return givenKey === key; | |
} | |
return { get, set, has }; | |
} | |
// 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; | |
}; | |
} | |
// This differs from my other versions by dealing directly with stores | |
// rather than other memoize functions. | |
function createTieredMemoizer(options = {}) { | |
const { | |
stores = [], | |
defaultStore = singleValueStore, | |
} = options; | |
return function memoize(fn) { | |
function getNewRecordFor(n) { | |
return { | |
store: (stores[n] || defaultStore)(), | |
// We can't eagerly put anything here because we don't know the args. | |
result: null, | |
}; | |
} | |
const rootRecord = getNewRecordFor(0); | |
return function memoizedFn(...args) { | |
const record = args.reduce( | |
(nextRecord, arg, i) => { | |
if (!nextRecord.store.has(arg)) { | |
nextRecord.store.set(arg, getNewRecordFor(i + 1)); | |
} | |
return nextRecord.store.get(arg); | |
}, | |
rootRecord | |
); | |
if (!record.result) { | |
record.result = memoizeApplication(fn, args); | |
} | |
return record.result(); | |
}; | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment