In this post, I’d like to have a closer look at the Symbol data type in Ruby. A little while back I was sitting with another software engineer discussing how to optimally solve a particular problem. After a bit of back and forth debate and some solid collaborative brainstorming we settled on what we felt was the best overall approach but we decided to spend a few moments discussing any potential targeted optimizations that we might be able to make to eke out just a little bit better performance. I tossed out the idea of using a Symbol, a relatively commonly used data type in Ruby, in favor of a String. The engineer I was working with wasn’t familiar with Symbols so he asked me to explain.
I tried to do so but I quickly came to the realization that I really needed to do a little reading before potentially misleading someone else. Symbols are so common in even basic Ruby programming that I hadn’t considered that they might be rarely (if ever) used in other languages. It turns out that in many languages neither symbols nor their analogs are a supported data type.
Properties of Symbols
At first glance, Symbols in Ruby seem to have a good deal in common with Strings. They are both objects and they both can be used to represent a word. In fact, although Symbol object do not have all of the same methods as String objects they do have decidedly String-like methods such as
Symbols are distinct from Strings, however, and one of the most obvious differences between the two is that Symbols are immutable. In this sense, Symbols can be said to resemble Constants. While strings can be made immutable through
#freeze, Symbols are inherently immutable. Symbols can also be faster to work with than a String because each reference to a Symbol having the same value uses the exact same object in memory instead of creating an additional instance of the class would be the case with a String.
Uses for Symbols
Symbols are often used in place of Strings as the keys in a Hash and, as I was suggesting in this particular instance, they can also be used as the value when the Symbol is standing in as a representation for a particular state/status. For example if a given vehicle object is either parked, in drive, or in reverse, one could set the vehicle objects status to
:drive. This approach is easier for developers to work with than using an integer (i.e.
3) more convenient than using a constant (i.e.
PARKED = "parked") and both more reliable and more performant than using a string (i.e.
Another common use of symbols is when passing a method name as an argument to another method like in the final line of this example code:
class Klass def hello(*args) "Hello " + args.join(' ') end end k = Klass.new k.send :hello, "gentle", "readers" #=> "Hello gentle readers"
Symbols also show up as arguments for the heavily used
attr_writer methods for defining class getters and setters.