On Feb 11, 2014, at 6:40 AM, Claude Pache wrote:
> According to the current version of the ES6 spec [1], `Symbol(desc)`, when
> `desc` is not `undefined`, coerces its argument to a string and uses it as a
> description for a newly created symbol. In particular, if `sym` is a symbol,
> `Symbol(sym)` throws a TypeError (it can't be coerced to string).
>
> Intuitively, I would expect that `Symbol(sym)` just returns `sym`, just like
> `Number(num)` returns `num`, or, more generally, just like `Primitive(x)`
> casts its argument to the corresponding primitive.
>
> What do you think?
>
I can't find any explicit mention of this in the meeting notes [1] where we
decided to make Symbol a primitive type with a wrapper class. However, I made
the appropriate changes to the spec. immediately after that meeting when the
discussion was fresh in my mind and I still think that throwing on Symbol(sym)
is the right thing to do:
For the other primitive/wrapper types the following conventions apply:
new Wrapper(prim) //always creates a new Wrapper instances wrapping the
supplied primitive value
Wrapper(prim) //always returns a primitive value derived by
coercing the argument to the appropriate primitive type. Returns prim if same
type.
At [1] we made different decisions for symbols and Symbol wrappers :
new Symbol(arg) // always throws, we don't support explicit creation of
Symbol wrapper objects
Symbol(arg) // always returns a new, not previously observed,
primitive symbol value
We made new Symbol throw to avoid the silent mistake where somebody uses it
thinking they are actually creating a new symbol value rather than a wrapper
object. Instead we decide to make a direct call to Symbol the only way (other
than Symbol.for) to access a new previously unobserved symbol value.
Symbol("string") is a symbol factory call, not a coercion of "string" to a
symbol. The argument is not a value to be coerced to symbol but a string value
that is part of the state of the new symbol value. In particular:
console.log(Symbol("x") === Symbol("x")) //false, each call to Symbol
returns a new unique symbol value
If Symbol(sym) returned sym, that would break the invariant that calling Symbol
always produces a new symbol value. Rather that reenforcing the fact the Symbol
has its own usage patterns that are different from Number/String/Boolean it
would partially blur that distinction.
ToString(symbolValue) throws because we don't want people doing string
concatenation to a symbol thinking they are manipulating a string property key.
ToString(symbolWrapper) just does a normal symbolWrapper.toString() call.
It would be consistent with the use of Symbol(foo) to allow Symbol(symbolValue)
and to internally perform symbolValue.toString() [note implicit wrapping via
property access) . However, that would still create a new unique symbol value
which probably isn't what the programmer actually intended. Another silent
mistake.
When all these factors are considered, I think what is currently specified is
just fine.
Allen
[1]: https://github.com/rwaldron/tc39-notes/blob/master/es6/2013-09/sept-18.md _______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss