top | item 8809277

(no title)

Gorkys | 11 years ago

Could anybody explain what problems this was designed to solve?

discuss

order

pilif|11 years ago

Same use (albeit with less nice syntax) as the ruby symbols.

Many frameworks based on ruby (like Rails) make heavy use of symbols.

They are handy as they are immutable, very cheaply comparable for equality and (in ruby) very light on syntax and they can be made out of thin air whenever you need one.

    some_array[:foo] = 'bar'
instead of

    FOO=0
    some_array[FOO] = 'bar';
(think how error prone it's going to be to add more keys like this. Forgotten declarations, duplication declarations and so on).

You could use strings, but they are often heap-allocated (slow) and sometimes (ruby) even mutable and thus way more expensive to compare for equality and require some kind of hashing to put them as keys into hash tables. Symbols don't. And never conflict.

k__|11 years ago

My idea of them was, they are like string-identifiers, but instead of creating a new string for every string-literal the symbol-literal creates one global, immutable instance.

spion|11 years ago

The main reason why Symbols were added AFAIK is to specify protocols / interfaces. Right now, duck typing is all we have in JS.

How do you check if an object is a Promise? You do `(typeof obj.then === 'function')`. Is this good? No, not really, especially not when the language reserves such a word - the problem is that they're global names and can easily conflict with existing methods.

In contrast, a symbol is used for the Iterator protocol [1]. You implement the protocol by adding a method to your object at the key "Symbol.iterator" that returns an iterator object. Unlike with string keys, its impossible for someone to have already used Symbol.iterator as a key before: the value didn't exist at all. As a result, this feature lets ES.next and libraries define new protocols without the need to come up with unique method names that aren't used in any library.

[1]: https://developer.mozilla.org/en/docs/Web/JavaScript/Guide/T...

Arnavion|11 years ago

In addition to the other replies, Symbols were at one point meant to be used for implementing private visibility in classes - the idea being that the private fields of an object would only be visible inside the class closure, preventing external code from being able to access them. However, private has been backed off from ES6 now.

chriswarbo|11 years ago

To be clear, "private" variables (including "methods", ie. variables bound to functions) can be implemented anywhere using lexical scope; whether you're pretending to have "classes" or not.

The feature which symbols offer is unforgeable contracts. These offer some benefits of type systems and module systems (AKA existential type systems). Any time we want to restrict access to some value, we can "seal" it by generating a new symbol and using that as its key in an object/mapping. We can pass the symbol to the code we want to "unseal" it, whilst the object itself can get passed around anywhere at all, without anyone being able to extract or replace the value until it reaches the "unsealer".

To see why this would be useful for "private visibility", the trick is not that we're hiding the values to everyone outside our lexical scope (which is trivial, since that's what lexical scope is); it's that we can allow access to these values, via functions which check that they're given the correct symbol. In other words, we can have our code "recognise" when some other code should be given access. If we limit ourselves to making "classes", where the symbol is in-scope in the "constructor" and doesn't leak out, then we have a primitive form of type-checking; if we're given the correct symbol, the other code must be of the same "class", so we might decide to let it see our "privates".

Of course, that's just a degenerate edge-case. There are all kinds of other uses, for example section XII of Harper's Practical Foundations for Programming Languages is dedicated to the topic http://www.cs.cmu.edu/~rwh/plbook/book.pdf

ajuc|11 years ago

It seems they can be used as a little safer enums, like :keywords in clojure. It can come handy if you want to add method to object that nobody will overwrite by accident.

But clojure was designed around :keywords, while js was designed around strings as property names. Adding another possibility now complicates everything.

I don't know if I like it.

nailer|11 years ago

I think you'd add methods nobody can overwrite using Object. defineProperty(), which is an ES5 thing.

rmrfrmrf|11 years ago

Seems like it could be used as a way to lazily copy objects; a solution like this could make a lot of sense if, say, a server had entire objects instantiated and the client only needs to know they exist, but not what each object contains.

pluma|11 years ago

Unique (derived) tokens that are not equal to any other value.

For example, symbols let you implement a map data structure without having to worry about shadowing built-in properties of the object.

ksherlock|11 years ago

If you have Symbols, you also have Map and WeakMap which don't have that problem.