A different semantics for WeakMap#get default value

Jason Orendorff jason.orendorff at gmail.com
Wed Jan 18 11:07:23 PST 2012


On Mon, Jan 16, 2012 at 2:09 PM, David Bruant <bruant.d at gmail.com> wrote:
> Hi,
>
> I recently wrote some code using WeakMaps and the following pattern
> keeps coming over and over:
> -----
> var v = wm.get(o);
> if(v === undefined){
>    v = someValue;
>    wm.set(o, v);
> }

Yes, this pattern is common. In 2000, Guido van Rossum added the
dict.setdefault method to Python in order to address this need.

Six years later, he had come to consider it a failure.
  http://mail.python.org/pipermail/python-dev/2006-February/061169.html

I think the setdefault method failed for three reasons:

1. Its second argument was a value, not a factory function.

2. It just wasn't intuitive. Even to the people most familiar with it,
it was always a conscious effort to read or write code using
setdefault.

3. It required programmers to repeat themselves. The default value had
to be specified every place the map was queried rather than just once
at the point where the data structure was created.

The result of the discussion linked above was the introduction of
collections.defaultdict to the Python standard library:
  http://docs.python.org/library/collections.html#defaultdict-objects

To me, defaultdict was a relief, and long overdue. It solved all three
problems with setdefault. I've been using it happily ever since. Ruby
has a similar feature built into its core Hash type.

So, what about ECMAScript? I think problems 2 and 3 apply to the
various getset/getOrSet/getIfAbsentSet ideas proposed in this thread.
Here is my proposal:

    WeakMap.prototype.force = function (key) {
        if (this.has(key))
            return this.get(key);
        var v = this.default(key);
        this.set(key, v);
        return v;
    };

If a particular Map or WeakMap is intended to be used with force(),
the program must supply it with a .default() method, which it could do
just by assignment, maps being extensible objects:

    var table = new WeakMap;
    table.default = function () { return new Array; };

(The name "force" is intended to evoke mutation and lazy evaluation.
Maybe that's too obscure. It could be called "require" instead, which
reads like a slightly stronger form of "get".)

-j


More information about the es-discuss mailing list