Allen Wirfs-Brock (2013-07-15T17:44:23.000Z)
On Jul 15, 2013, at 9:40 AM, Andreas Rossberg wrote:

> On 15 July 2013 18:24, Allen Wirfs-Brock <allen at wirfs-brock.com> wrote:
>> On Jul 15, 2013, at 8:35 AM, André Bargull wrote:
>>> Allen (cc-ed) changed symbols back to objects in draft rev 16
>>> (https://bugs.ecmascript.org/show_bug.cgi?id=1546#c2), so I guess Object(x)
>>> will still work in ES6 to test for object types.
>> 
>> Correct, Symbols as primitive values were just causing too many issues.
> 
> Oh. I wasn't aware of this. Is this just a spec language change, or is
> it a semantic change? If the latter, then I have to disagree with the
> change.


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.

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.

If you have wrapper objects, then you have visible semantics such as:
   let s = Symbol();
   console.log(Object(s) === Object(s));  //false, because each call to Object produces a new wrapper object
   console(s === Object(s));   //false, because each call to Object produces a new wrapper object

If you have symbols as primitive values, but no wrappers you get:
   console.log(Object(s) === Object(s));  //TypeError
   console(s === Object(s));   //TypeError

If you have symbols as exotic objects  you get:
   console.log(Object(s) === Object(s));  //true
   console(s === Object(s));   //true

Because ES5 added auto-wrapping of primitive values within PutValue/GetValue, primitive values already act as if they were objects in most situations and except for the identify complications numbers/strings/booleans values can generally be used and reasoned about as if they were instances of Number/String/Boolean.   We really should avoid adding new  primitive types and wrapper objects.  Value objects are the way to go, starting with Symbol.

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.

I would be interested in hearing if there are places in your implementation where specifying symbols as exotic objects will make an actual performance difference when using symbols as property keys. 

> 
>> Essentially, everyplace in the spec. that  needs an object had to be updated
>> to explicit deal with Symbols.
> 
> Allen, can you elaborate where symbols introduced cases that did not
> already have to be handled for other primitive types?

Every place that did a ToObject, or equivalent.  I'm pushing out a new spec. draft today or tomorrow and you can see the changes there.

Allen
domenic at domenicdenicola.com (2013-07-23T17:40:56.564Z)
On Jul 15, 2013, at 9:40 AM, Andreas Rossberg wrote:

> Oh. I wasn't aware of this. Is this just a spec language change, or is
> it a semantic change? If the latter, then I have to disagree with the
> change.


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.

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.

If you have wrapper objects, then you have visible semantics such as:

```js
let s = Symbol();
console.log(Object(s) === Object(s));  //false, because each call to Object produces a new wrapper object
console(s === Object(s));   //false, because each call to Object produces a new wrapper object
```

If you have symbols as primitive values, but no wrappers you get:

```js
console.log(Object(s) === Object(s));  //TypeError
console(s === Object(s));   //TypeError
```

If you have symbols as exotic objects  you get:

```js
console.log(Object(s) === Object(s));  //true
console(s === Object(s));   //true
```

Because ES5 added auto-wrapping of primitive values within PutValue/GetValue, primitive values already act as if they were objects in most situations and except for the identify complications numbers/strings/booleans values can generally be used and reasoned about as if they were instances of Number/String/Boolean.   We really should avoid adding new  primitive types and wrapper objects.  Value objects are the way to go, starting with Symbol.

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.

I would be interested in hearing if there are places in your implementation where specifying symbols as exotic objects will make an actual performance difference when using symbols as property keys. 

> Allen, can you elaborate where symbols introduced cases that did not
> already have to be handled for other primitive types?

Every place that did a ToObject, or equivalent.  I'm pushing out a new spec. draft today or tomorrow and you can see the changes there.