(Map|Set|WeakMap)#set() returns `this` ?

Mark S. Miller erights at google.com
Wed Dec 5 10:04:13 PST 2012


On Wed, Dec 5, 2012 at 1:50 AM, Jussi Kalliokoski
<jussi.kalliokoski at gmail.com> wrote:
> My 2 cents against the windmills...
>
> I personally think returning `this` in absence of any meaningful value (and
> chaining in general) is a bad pattern. Chaining leads to worse readability
> (there's nothing subjective about this, if you have to scan the code to
> another page to figure out which object the code is interacting with, it's
> bad readability)

This is an excellent point, and has changed my mind. I return to not
supporting the "return this" for these cases. Thanks.


 and returning this is more future-hostile than returning
> nothing. If we in the future come up with something actually useful the
> function could return, there's no turning back if it already returns `this`.
> For set(), meaningful values include the value that was set, a boolean
> whether the value was added or replaced, etc., whereas `this` is meaningless
> since you have it already. Returning `this` in absence of meaningful values
> is also a mental overhead: "Does this return a meaningful value, or just
> this, so can I chain it?"
>
> I, like Andrea, have dreamed that Array#push() returned the value I passed
> to it (although the reason that it doesn't is probably that you can pass
> multiple values to push), I have a lot of cases where I've hoped that I
> could do this:
>
> return objects.push({
>   foo: bar,
>   baz: tar
> })
>
> instead of:
>
> var newObject = {
>   foo: bar,
>   baz: tar
> }
> objects.push(newObject)
> return newObject
>
> For Array#push() to have returned `this`, I can't think of a single line of
> code it would have made simpler.
>
> Another thing is that set() returning the value that was set is also
> consistent with language semantics in that `(a = 1)` has the value of 1.
>
> I'd like to see a better way to do chaining than functions returning `this`,
> like the monocle mustache.
>
> Cheers,
> Jussi
>
> On Wed, Dec 5, 2012 at 3:30 AM, Andrea Giammarchi
> <andrea.giammarchi at gmail.com> wrote:
>>
>> as discussed before, the problem with setDefault() approach you are
>> suggesting is that the dict(), at least in JS, will be created in any case.
>>
>> var newDict = a.setDefault(k1, dict());
>>
>> above operation will invoke dict() regardless k1 was present or less and
>> this is not good for anyone: RAM, CPU, GC, etc
>>
>> the initial pattern is and wants to be like that so that not a single
>> pointless operation is performed when/if the key is already there.
>>
>> var o = obj.has(key) ? obj.get(key) : obj.set(key, dict()); // <== see
>> dict, never called if key
>>
>> quick and dirty
>>
>> var o = obj.get(key) || obj.set(key, dict());
>>
>> With current pattern, and my only concern is that after this decision
>> every other `set()` like pattern will return this even where not optimal, I
>> have to do
>>
>> var o = obj.has(key) ? obj.get(key) : obj.set(key, dict()).get(key);
>>
>> meh ... but I can survive :D
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>> On Tue, Dec 4, 2012 at 4:49 PM, Tab Atkins Jr. <jackalmage at gmail.com>
>> wrote:
>>>
>>> On Mon, Dec 3, 2012 at 2:21 PM, Andrea Giammarchi
>>> <andrea.giammarchi at gmail.com> wrote:
>>> > IMHO, a set(key, value) should return the value as it is when you
>>> > address a
>>> > value
>>> >
>>> > var o = m.get(k) || m.set(k, v); // o === v
>>> >
>>> > // equivalent of
>>> >
>>> > var o = m[k] || (m[k] = v); // o === v
>>>
>>> If this pattern is considered sufficiently useful (I think it is), we
>>> should handle it directly, as Python does.  Python dicts have a
>>> setDefault(key, value) method which implements this pattern exactly -
>>> if the key is in the dict, it returns its associated value (acts like
>>> a plain get()); if it's not, it sets the key to the passed value and
>>> then returns it.  Using this pattern is not only clearer, but avoids
>>> repetition (of "m" and "k" in your example), and actually chains - I
>>> use setDefault all the time when working with nested dicts.
>>>
>>> (For example, if I have a sparse 2d structure implemented with nested
>>> dicts, I can safely get/set a terminal value with code like
>>> "a.setDefault(k1, dict()).set(k2, v)".  If that branch hadn't been
>>> touched before, this creates the nested dict for me.  If it has, I
>>> create a throwaway empty dict, which is cheap.  If JS ever grows
>>> macros, you can avoid the junk dict as well.)
>>>
>>> I prefer the plain methods to work as they are currently specified,
>>> where they return this.
>>>
>>> ~TJ
>>
>>
>>
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>>
>
>
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>



--
    Cheers,
    --MarkM


More information about the es-discuss mailing list