I just started reading this book Eloquent Ruby and I have reached the chapter about Symbols in Ruby.
Strings in Ruby are mutable, which means each string allocate memory since the content can change, and even though the content is equal. If I need a mutable String in Java I would use StringBuffer. However since regular Java Strings are immutable one String object can be shared by multiple references. So if I had two regular Strings with the content of “Hello World”, both references would point to the same object.
So is the purpose of Symbols in Ruby actually the same as “normal” String objects in Java? Is it a feature given to the programmer to optimize memory?
Is something of what I written here true? Or have I misunderstood the concept of Symbols?
Symbols are close to strings in Ruby, but they are not the equivalent to regular Java strings, although they, too, do share some commonalities such as immutability. But there is a slight difference – there is more than one way to obtain a reference to a Symbol (more on that later on).
In Ruby, it is entirely possible to convert the two back and forth. There is String#to_sym to convert a String into a Symbol and there is Symbol#to_s to convert a Symbol into a String. So what is the difference?
To quote the RDoc for Symbol:
Symbols are unique identifiers. If the Ruby interpreter stumbles over let’s say
:mysymbolfor the first time, here is what happens: Internally, the symbol gets stored in a table if it doesn’t exist yet (much like the “symbol table” used by parsers; this happens using the C functionrb_internin CRuby/MRI), otherwise Ruby will look up the existing value in the table and use that. After the symbol gets created and stored in the table, from then on wherever you refer to the Symbol:mysymbol, you will get the same object, the one that was stored in that table.Consider this piece of code:
to notice the difference. It illustrates the major difference between Java Strings and Ruby Symbols. If you want object equality for Strings in Java you will only achieve it if you compare exactly the same reference of that String, whereas in Ruby it’s possible to get the reference to a Symbol in multiple ways as you saw in the example above.
The uniqueness of Symbols makes them perfect keys in hashes: the lookup performance is improved compared to regular Strings since you don’t have to hash your key explicitly as it would be required by a String, you can simply use the Symbol’s unique identifier for the lookup directly. By writing
:somesymbolyou tell Ruby to “give me that one thing that you stored under the identifier ‘somesymbol'”. So symbols are your first choice when you need to uniquely identify things as in:But, as Jim Weirich points out in the article below, Symbols are not Strings, not even in the duck-typing sense. You can’t concatenate them or retrieve their size or get substrings from them (unless you convert them to Strings first, that is). So the question when to use Strings is easy – as Jim puts it:
Some articles on the topic: