On Jul 16, 2013, at 4:34 AM, Andreas Rossberg wrote:

> On 15 July 2013 19:44, Allen Wirfs-Brock <al...@wirfs-brock.com> wrote:
>> The is primarily an internal spec. change.  Many internal operations within 
>> the spec. require objects as parameters.  This required inserting inserting 
>> explicit guards in p=many places within the specification and remembering to 
>> include them in new algorithms. At the March meeting you objected to the 
>> "two pages of specification" required to define Symbols as exotic objects.  
>> It turned out that those two pages were fair simpler and less intrusive than 
>> the all the individual spec. changes (and ongoing additions) that were 
>> needed to support symbols as primitive values.
> 
> I'm afraid I still don't see how this is the case (the draft diffs are
> not particularly easy to read). Almost everything should be handled by
> ToObject creating a wrapper object in the traditional places,
> shouldn't it? What are the contexts where (a) an object is required,
> but (b) a symbol would behave differently from existing primitives?
> 
> 
>> User visible semantics comes down to whether or not there is a Symbol 
>> wrapper object. As far as I can tell, tell from the notes, there was no 
>> consensus WRT Symbol wrappers record in March and when I tried to convert to 
>> Symbols as primitive values in the spec. I don't provide such wrappers.  
>> Instead, I made ToObject throw for symbols values.
> 
> OK, that might explain the difficulty you faced. My understanding of
> the March agreement certainly was that there is a wrapper object,
> consistent with other primitive types. And I'm pretty sure that that
> makes the spec quite simple and regular.

Yes, wrappers would make it easier, but my take away from the meeting and 
subsequent discussion was that we didn't want to add any more observable 
wrappers. 
> 
> 
>> We really should avoid adding new  primitive types and wrapper objects.  
>> Value objects are the way to go, starting with Symbol.
> 
> I'd argue for the contrary, namely that we should avoid artificially
> cramping more inappropriate concepts into the notion of 'object'!
> These are not objects by any useful definition of the word, despite
> the MOP being rich enough to support them as degenerate cases.

Clearly I disagree. In ES and other polymorphic object-based languages, objects 
are really the basis for uniformity of references.  Any abstraction can be 
represented as an object and any operation can be manifested as method 
invocations upon an object. 

It is the ES primitive types that introduce non-uniformity that either needs to 
be special cased or partially hidden behind hacks such as automatic conversion 
to wrapper objects. Clearly at an implementation level you want to have 
optimized representations of certain kinds of entities.  You can get there two 
different ways.  You can expose the optimized representation as "primitive 
types" that requires user level special casing or you can uniformly expose 
everything as an "object" and let the implementation opaquely use special case 
representations where it suits it.

It seems clear to me, that if  you want to support an open ended set of new 
abstractions you need to go the uniform objects route.   We're stuck with 
numbers, strings, and booleans and their corresponding wrappers. We don't need 
more special cases at that level.

> 
> 
>> I'd be interested in hearing how this makes any difference to you from an 
>> implementation perspective.  Even when symbols are specified as exotic 
>> objects you can still encode them as immediate values, just like you would a 
>> SmallInteger in Smalltalk. It's only when actual object MOP operations are 
>> applied to them that you should have to do any special casing but these are 
>> generally the same situations where you would have to auto-wrap primitive 
>> values.
> 
> The difference is that with real primitives + wrapper objects every
> respective operation has a single place where it does the ToObject
> conversion (which exists already), and downstream you can easily make
> it an invariant that what you've got is an ordinary object with an
> ordinary object representation. No special casing required.
> 
> If, on the other hand, you make new primitives pseudo-objects, but
> still want to represent them efficiently, then all parts that deal
> with objects now also have to deal with those denormal
> representations. You say "only actual MOP operations", but surely
> there are several times more occurrences of those than of ToObject. It
> involves the majority of language operations, and in contemporary
> implementations, every one of them potentially has a dozen or more
> possible implementations.

Sounds like your are concerned about special casing MOP dispatches on 
primitives representations.  A good concern.  However, I don't actually see 
much benefit of a primitive non-dispatchable representation for symbols and if 
you do, you could still hide it in ToObject.  Nothing saying you can't have 
internal wrapper objects and be careful not to leak themselves to the language 
level.  


> 
> Alternatively, you could introduce two different representations for
> these pseudo-objects and normalise their representation to a real
> object wherever you perform ToObject. That is, you essentially
> introduce the wrapper internally in the implementation. But then you
> have the dual problem: because this has to be transparent, now all
> contexts that expect a proper symbol also have to deal with wrapped
> symbols (and probably have to reverse the normalisation). And those
> are quite a few as well. Likewise, you have to special-case equality,
> maps, and similar generic operations.

I don't buy it.  For symbols you don't inherently have to have two different 
representations. The use of MOP operations on symbols is going to be very rare. 
Any you have two have some sort generalized exotic object MOP dispatch 
mechanism.  Because MOP operations on symbols are never important, so that 
representation should be fine from the object perspective.  For actual property 
access, its only the identify of the symbol that matters.

I sense, that you issue may be that you have implementation issues relating to 
property looking/caching that perhaps relates to your representation of string 
primitive values.  Is your issue that a symbol primitive typed modeled after 
strings will be easer to fit into your implementation?  If so, it isn't clear 
that this ease of retrofit consideration carries over to other implementations.

> Whichever path you take, artificially unifying two different concepts
> that have completely disjoint uses and requirements is not going to
> make anything simpler.
> 
> All this may be a worthwhile price to pay if it actually added any
> value to the language. But I don't see a notable benefit for
> programmers either. Am I missing something?

Yes, it's drawing a line and saying no added special case primitive types and 
no new wrapper objects. Starting with ES6 all new abstractions can be 
conceptualized as "objects".

Allen



_______________________________________________
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to