RubyGreenBlue

What are Ruby Symbols

Posted by keith 8 months ago

One of the hardest things to explain about Ruby (especially to newcomers) is what symbols are. Many explanations of symbols that I see or hear often only cover a low-level/technical difference between symbols and strings. That is, that symbols use one memory location for each unique instance whereas strings use separate memory locations for each instance. Also that symbols are kept around in memory for the life of the program while strings get cleaned up when they are no longer used.

While these differences are accurate, they are just implementation details and not really what Ruby symbols are all about and those who quote only these differences by way of explanation of what Ruby symbols are, are missing the point.

What Ruby symbols are really about is beauty and semantics. Ruby symbols give the programmer the distinction between identity and information.

Consider this method call:

validates_presence_of :firstname, :lastname, :on => :create, :message => "can't be blank"

and if we single out

:message => "can't be blank"

:message is a symbol and "can't be blank" is a string. We could have easily written this statement like:

"message" => "can't be blank"

But the difference here is that :message is just a label for something, some concept, that a part of our program needs to work with. Whereas "can't be blank" is actual data or information. Another way to look at it is that we could mess with one of the two and the program would not care but if we mess with the other and the program does care.

If I change it to:

:my_message => "can't be blank"

The program no longer works as it did before. The method does not look for anything labeled :my_message. It is not a concept it knows about. The label :message is there only so the programmer and the method can talk about the same concept.

Now if I change it to:

:message => "can't be blank, sorry about that."

or

:message => "darf nicht leer sein"

The program still works as it did before, it just displays a different message. The "can't be blank, sorry about that." is clearly different to :message. It's not a label or an identity at all, it's information.

Many other languages don't have this distinction between information and identity, or at least not in such a nice, convenient way. As a result, strings are often used to perform the task of labeling.

$car = array ("weight"=>"1000", "unit_of_measure"=>"kg", "year"=>"2004", "price"=>"7000");

If the program knows about the concept of weight and unit_of_measure, using strings for those labels doesn't quite feel right.

car = {:weight => '1000', :unit_of_measure => 'kg', :year => '2004', :price => '7000'}

Now we have a separation between the concepts our program deals with and the associated data. And with syntax highlighting it reads so much nicer.

Take this example again

validates_presence_of :firstname, :lastname, :on => :create, :message => "can't be blank"

It reads so much nicer and is easier to see which bits, if changed, will affect the semantics of the program and which bits won't, but if we use strings for our labels, we lose that distinction.

validates_presence_of "firstname", "lastname", "on" => "create", "message" => "can't be blank"

An easy way to work out if you should use a symbol or a string is this: Does the program care about the thing I am typing, or does the user care about it?

  • if the program cares:

    :symbol
    
  • if the user cares:

    "string"