In order to learn about using WeakMap
, I came up with the following example to track function invocations:
var map = new WeakMap();
function countFunctionInvocations(func) {
return function(...args) {
map.set(func, (map.get(func) || 0)+1);
return func.apply(this, args);
}
};
const _add = (x,y) => x+y;
const _inc = x => x+1;
const add = countFunctionInvocations(_add);
const inc = countFunctionInvocations(_inc);
add(2,3);
add(1,2);
add(2,3);
add(2,3);
inc(inc(1));
console.log(map.get(_add), map.get(_inc));
// 4 2
What would be a cleaner way to implement this, as I have to alias the functions back and forth, for example from add
to _add
and back to add
. Additionally, is the above a legitimate usage of Weakmap?
The use of the WeakMap is pretty weird - as you've noticed, if you want to look things up with it with functions, you have to store those functions in variables, which are separate from the count-invokified function. It makes things awkward and a WeakMap doesn't seem to have a net benefit over a plain object, as long as you don't have function name collisions.
If this is allowed by what you're looking for, you could pass another argument to
countFunctionInvocations
indicating the name, allowing you to pass a (concise, anonymous) arrow function.I mean, it could be used, but as we've noticed - it's awkward to have to have two separate references to a function - one being the base function, and one being the one transformed by
countFunctionInvocations
.That said, this is certainly a legitimate usage of WeakMap over a Map, because it allows the function (and its invoke count) to be garbage collected once nothing else can reference it.
I guess another option would be for the returned function to be the one put into the Map, so that you only have one identifier on the outside, but it'd require a
function
or a second argument to indicate the name of the function, otherwise the inside ofcountFunctionInvocations
would only see an anonymous function without a name.