Different cache id resolution per argument
amaury1093 opened this issue · comments
Amaury commented
My function has signature:
function myFunction(a: object, b: object): void;
const memoized = memoize(f);
If I understood well, when I memoize that, it memoizes by object reference:
memoize({ foo: 'bar' }, { bar: 'qux' });
memoize({ foo: 'bar' }, { bar: 'qux' }); // Cache NOT hit
I wish to memoize the 1st argument by its serialized version, and the 2nd argument by object reference. Namely, if:
const first = { foo: 'bar' };
const second = { bar: 'qux' };
The I want the 3 following tests to pass:
Test 1:
memoize(first, second);
memoize({ foo: 'bar' }, second); // Cache hit
memoize(first, second); // Cache hit
Test 2:
memoize(first, second);
memoize(first, { bar: 'qux' }); // Cache not hit
memoize({ foo: 'bar' }, { bar: 'qux' }); // Cache not hit
Test 3:
memoize({ foo: 'bar' }, second);
memoize({ foo: 'bar' }, second); // Cache hit
memoize(first, second); // Cache hit
Is that possible with the current version?
Mariusz Nowak commented
Is that possible with the current version?
Yes it is, but you need to provide your own normalizer, which can work as e.g.:
const idCounter = 0;
const idMap = new WeakMap();
const getObjectId = obj => {
if (idMap.has(obj)) return iMap.get(obj);
const id = ++idCounter;
idMap.set(obj, id);
return id;
};
const memoized = memoize(f, {
normalizer: ([a, b]) => `${getObjectId(b)},${JSON.stringify(a)}`
});
Mariusz Nowak commented
Alternatively, if it would be the case where first argument is expected to be mapped by reference and second by serialized representation, it can be done more straightforward with weak
mode:
const memoizeWeak = require("memoizee/weak");
const memoized = memoizeWeak(f, { normalizer: ([,b]) => JSON.stringify(b) });