Comments on Sept Meeting Notes

Domenic Denicola domenic at domenicdenicola.com
Thu Sep 26 15:48:53 PDT 2013


If it's going to be strings, it should be dunder, for consistency with the already-existing cohort of proto/[define|lookup][G|S]etter. Having two magic namespacing conventions in the language is insanity.

I don't understand why this is happening. There was fairly strong consensus on symbols at the last meeting, and nothing new has been brought to the table. Why are people's opinions suddenly changing? Vague fearmongering about "complexity"? Symbols are a good solution to a real problem, much better than strings.

> On Sep 26, 2013, at 16:59, "Brendan Eich" <brendan at mozilla.com> wrote:
> 
> @ is the new dunder -- dunder at -- dat.
> 
> Among the no-symbol proposals, I like this best. (GUIDs, shudder.)
> 
> /be
> 
>> Kevin Smith <mailto:zenparsing at gmail.com>
>> September 26, 2013 6:11 AM
>> After thinking this over, I still remain unconvinced that symbols are the right solution to the problem. Besides the fact that they introduce (ever more) complexity to the object model, they simply do not work as a duck-typing strategy for the real, *multi-realm* world of Javascript. Sure, we can make a special case of standard library symbols such that they maintain identity across realms. But a solution which only works for special cases isn't a very good solution, is it?
>> 
>> Here is another proposal which avoids these pitfalls:
>> 
>> 1) Identify all meta-layer hooks using a string that is not an identifier. The actual string used doesn't matter in this proposal, but for illustration purposes I'll use an "@"-prefix.
>> 
>> 2) Define all meta-layer hooks as functions. Testing for the hook will involve [[Get]] followed by [[IsCallable]].
>> 
>> For example, defining an iterable:
>> 
>> class C { "@iterator"(...args) { /* ... */ } }
>> 
>> Overriding the string tag:
>> 
>> class C { "@toStringTag"() { return "[object C]"; } }
>> 
>> - Since the property name is a non-identifer, it is unlikely to collide with any object members.
>> - Since the value of the hook must be a function, it is unlikely to collide with keys in an object-as-map (e.g. a JSON object).
>> - Since it is just a string, it requires no changes to property semantics, and it trivially works across realms.
>> 
>> { Kevin }
>> 
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>> Kevin Smith <mailto:zenparsing at gmail.com>
>> September 25, 2013 11:53 AM
>> I think that your example _might_ do it, although I'll have to think more about it tonight.
>> 
>> If so, then the justification for symbols at this point is based on the dual use of JS objects as programming abstractions and as a key-value data structure. Oh, javascript... : )
>> 
>> { Kevin }
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>> Domenic Denicola <mailto:domenic at domenicdenicola.com>
>> September 25, 2013 11:41 AM
>> From: Kevin Smith [zenparsing at gmail.com]
>> 
>>> I'm still not quite convinced that objects-as-maps make a truly isolated namespace necessary, however.  I would be convinced by a code example showing how a property of an object using arbitrary string keys could be misinterpreted as a meta-level property.
>> 
>>> I'll try to think of one...
>> 
>> The hard part of producing such examples is that most of the meta-level properties are functions (e.g. iterator), and thus it's not trivially easy to produce an object from `JSON.parse`ing user input. But there are some meta-level properties that are not functions, namely @@isRegExp, @@toStringTag, and @@unscopables.
>> 
>> So let's say that we decided to use a non-isolated namespace of strings, instead of unique symbols. Thus, we would have `"std:isRegExp"`, `"std:toStringTag"`, and `"std:unscopeables"`. Well, then simple code like this:
>> 
>> ```js
>> var requestBody = JSON.parse(req.body);
>> ```
>> 
>> could end up getting a very weird object, if I POSTed the string
>> 
>> ```
>> {
>>   "std:isRegExp": true,
>>   "std:toStringTag": "My Custom String Tag With Spaces and Punctuation!",
>>   "std:unscopeables": ["hasOwnProperty", "toString", "propertyIsEnumerable"]
>> }
>> ```
>> 
>> to that HTTP endpoint.
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>> 
>> Kevin Smith <mailto:zenparsing at gmail.com>
>> September 25, 2013 11:34 AM
>> 
>> 
>> Thanks, Domenic. I withdraw that aspect of the argument.
>> 
>> I'm still not quite convinced that objects-as-maps make a truly isolated namespace necessary, however. I would be convinced by a code example showing how a property of an object using arbitrary string keys could be misinterpreted as a meta-level property.
>> 
>> I'll try to think of one...
>> 
>> { Kevin }
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>> Domenic Denicola <mailto:domenic at domenicdenicola.com>
>> September 24, 2013 9:40 PM
>> 
>> I do not plan to switch to Map for string-keyed maps. I’ll be using `Object.create(null)` instead.
>> 
>> *From:*es-discuss [mailto:es-discuss-bounces at mozilla.org] *On Behalf Of *Kevin Smith
>> *Sent:* Wednesday, September 25, 2013 00:05
>> *To:* Tab Atkins Jr.
>> *Cc:* es-discuss
>> *Subject:* Re: Comments on Sept Meeting Notes
>> 
>>    This seems like a non-sequitur. Symbols aren't meant to help with the
>>    "object as map" use-case, and even if you tried to, they work terribly
>>    for it. They're meant for the "add an actual property/method without
>>    collision" use-case. Again, Maps seem like a non-sequitur here -
>>    using a Map doesn't aid with avoiding collisions.
>> 
>> Before Maps, I might use a regular object to store arbitrary string-to-value mappings. Say I'm counting the occurrences of terms appearing on es-discuss. The key "std:iterator" might actually occur. In that case we would have a collision with my proposed meta-level property name. But going forward, no one's going to use a regular object for arbitrary string keys - it's simply too error-prone. They'll use a Map instead. Which means that we don't have to worry about arbitrary string keys colliding with meta-level property names.
>> 
>> Now, one might argue that using the string "std:iterator" (or equivalent) would present a backward compatibility hazard for legacy code using objects as maps. I'll have to think about that one...
>> 
>> The argument is that, once you take out arbitrary string keys (as occur when using an object as map), a "namespaced" string provides sufficient collision resistance to make symbols unnecessary.
>> 
>>    How is this in any way better than:
>> 
>> 
>>    class C {
>>    std_iterator() { ... }
>>    }
>> 
>> The set of non-identifiers is less commonly used for member names by far, so it has that advantage. But I'm not really saying that "std:iterator" is better than "std_iterator". I'm saying that both are a simpler solution than symbols.
>> 
>> { Kevin }
>> 
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
> 



More information about the es-discuss mailing list