I really like Austin’s earlier blog about Symbols and how they are just names.
I think the real confusion around symbols is three fold:
- The colon in the name
- The name Symbol
- How they relate to Strings
To understand the utility of Symbols, and how they are really just “names”, lets focus on their utility. Our goal is to be able to pass some kind of named parameter around to various methods. How can we do that? Well, a very conventional way from programming is to use Strings:
This code is a simplier form of:
some_object.getParameter( String.new("age") )
What this means is that we have to create a new Ruby String object, pass it to getParameter and let it handle it from there. But we’re not really interested in the string data, we simply have to use it to get the word “age” into our method. We could have said:
If we had known that the 42nd parameter represented age. But it’s more convenient to ask by name, and the only way we have to do that is with a String.
Instead, we endeavor to create a new class type called a NamedParameter that we can use instead of a String, since we’re not interested in the String, per se, but just the concept of the named parameter of “age”.
So what this means is we could say:
some_object.getParameter( NamedParameter.new("age") )
Except, we haven’t gotten anywhere! We still have to use a String to get a name to the parameter.
How else can we do it?
some_object.getParameter( NamedParameter.new(age) )
The above code doesn’t work, because in this case age represents a local variable.
Thus, it seems we’re stuck, and have to use Strings to pass around named parameters.
However, we have this special Ruby class called Symbols. With a Symbol we’ve got a way to create a name that we can use in our program and pass around, and it isn’t a String. Instead it’s a unique identifier.
Now we can pass the name “age” into our getParameter method, and it’s not a String. The colon is just the way to tell the interpreter we’re using a Ruby Symbol. It could have been anything, if it was designed that way:
Who knows? The point is, it’s a way to get a name without having to create a Ruby String. There’s simply no other way to do it.
Once you get that, you can see that preferring Symbols to Strings when creating named parameters makes more sense. For one reason, you don’t need to use Strings for that kind of purpose - the only reason many of us do is because in our languages of familiarity it’s the only way to do it! The other reason is the touted performance penalty reasons - that is, every time a Symbol is used in your Ruby code it references the exact same object over and over again. With Strings, a new string is created every single time.
You can ask a symbol its name, via the to_s method, and it will return a String with that value in it. Perhaps that’s confusing as well, but what else is it supposed to return? The only other thing it could possibly return would be itself, and that probably isn’t very helpful.
So, as you can see, Symbols are a valuable addition to Ruby. We create them right in our code ( there’s no Symbol.new() - how would you name it…with a String? ). Then we can use them, instead of Strings, as names throughout the code.