trie-memoize
Version:
A memoization algorithm in which each function argument represents a new key, creating a trie of caches as defined by the array in your first argument.
89 lines (75 loc) • 1.77 kB
JavaScript
const createCache = obj => {
try {
// @ts-ignore
return new obj();
} catch (e) {
const cache = {};
return {
set(k, v) {
cache[k] = v;
},
get(k) {
return cache[k];
}
};
}
};
const memo = constructors => {
const depth = constructors.length,
baseCache = createCache(constructors[0]);
let base;
let map;
let i;
let node;
const one = depth === 1; // quicker access for one and two-argument functions
const g1 = args => (base = baseCache.get(args[0])) === void 0 || one ? base : base.get(args[1]);
const s1 = (args, value) => {
if (one) baseCache.set(args[0], value);else {
if ((base = baseCache.get(args[0])) === void 0) {
map = createCache(constructors[1]);
map.set(args[1], value);
baseCache.set(args[0], map);
} else {
base.set(args[1], value);
}
}
return value;
};
const g2 = args => {
node = baseCache;
for (i = 0; i < depth; i++) if ((node = node.get(args[i])) === void 0) return;
return node;
};
const s2 = (args, value) => {
node = baseCache;
for (i = 0; i < depth - 1; i++) {
if ((map = node.get(args[i])) === void 0) {
map = createCache(constructors[i + 1]);
node.set(args[i], map);
node = map;
} else {
node = map;
}
}
node.set(args[depth - 1], value);
return value;
};
return depth < 3 ? {
g: g1,
s: s1
} : {
g: g2,
s: s2
};
};
const memoize = (mapConstructors, fn) => {
let item;
const {
g,
s
} = memo(mapConstructors);
return function () {
return (item = g(arguments)) === void 0 ? s(arguments, fn.apply(null, arguments)) : item;
};
};
export default memoize;