In Ruby, a symbol is just an immutable string:
"hello " + "world" #=> "hello world"
:hello_ + :world #=> NoMethodError: undefined method `+' for :hello:Symbol
Being immutable makes symbols a safe and reliable reference, for example:
Object.methods => [:new, :allocate, :superclass, #etc..]
If Ruby were to use strings here, users would be able to modify the strings, thus ruining future calls of Object.methods
. This could be fixed by making copies of the strings each time the method is called, but that would be a huge memory footprint.
In fact, since Ruby knows symbols are never going to be modified, it saves each symbol only once, no matter how many times you declare it:
"hello".object_id #=> 9504940
"hello".object_id #=> 9565300
:hello.object_id #=> 1167708
:hello.object_id #=> 1167708
This takes the memory-saving potential of symbols even further, allowing you to use symbol literals in your code anywhere and everywhere with little memory overhead.
So, the round-about answer to your question: symbols can't be modified, but they're safer and more memory efficient; therefore, you should use them whenever you have a string that you know shouldn't be modified.
Symbols are used as the keys to hashes because:
- You should never modify the key of a hash while it's in the hash.
- Hashes require literal referencing a lot, ie
my_hash[:test]
, so it's more memory-efficient to use symbols.
As for method references: you can't reference a method directly, ie send(my_method())
because can't tell the difference between passing the method in and executing it. Strings could have been used here, but since a method's name never changes once defined, it makes more sense to represent the name as a symbol.