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.