Ruby symbols

 Jan, 06 - 2009   99 comments   Ruby

I keep seeing many programmers from different backgrounds are unable to get what Ruby symbols are, and though I do know that there are many great posts regarding this topic, and actually my intent is not to increase them by one :) , but I feel I have to clear few points regarding them.
So I’m trying to answer 2 important question here: What are Ruby symbols? and When to use them?

What are Ruby symbols?

Well, according to the API documentation:

Symbol objects represent names and some strings inside the Ruby interpreter. They are generated using the :name and :”string” literals syntax, and by the various to_sym methods. The same Symbol object will be created for a given name or string for the duration of a program’s execution, regardless of the context or meaning of that name. Thus if Fred is a constant in one context, a method in another, and a class in a third, the Symbol :Fred will be the same object in all three contexts.

Let’s walk over this long quote, point by point, but let’s first list all the points it has:

1-Symbol objects represent names and some strings inside the Ruby interpreter.
2-They are generated using the :name and :”string” literals syntax, and by the various to_sym methods.
3-The same Symbol object will be created for a given name or string for the duration of a program’s execution, regardless of the context or meaning of that name. Thus if Fred is a constant in one context, a method in another, and a class in a third, the Symbol :Fred will be the same object in all three contexts.

I’ll start with the 2nd point then get back to the rest, just before I do, please fire your irb:

We can create a symbol with various ways:

That was the easy part, now let’s get back to the first point, it says: “Symbol objects represent names and some strings inside the Ruby interpreter.” , what does that mean exactly?

In computer science there is a term called: Symbol table, where the compiler or the interpreter of the language stores all the identifiers of a source code in that table to reference them -specifically to be referenced by the Abstract Syntax Tree(AST).
Actually the data structure that represents the symbol table varies from one interpreter to another, but what we care for is Ruby, in Ruby, the symbol table stores various things like method names and symbol names(we will check why Ruby does so later on), and the value of a symbol is a unique integer value, that can’t be changed.

Now let’s take more in depth example, let’s explore the symbol table:

As you can see, when we defined the class ‘Dummy’ and more specifically when we defined the ‘hello_world’ method, it was added to the symbol table.
Let’s take another example:

Now let’s take the last point : “The same Symbol object will be created for a given name or string for the duration of a program’s execution, regardless of the context or meaning of that name. Thus if Fred is a constant in one context, a method in another, and a class in a third, the Symbol :Fred will be the same object in all three contexts.” ,so: Fred is :Fred wherever you see it and no matter what the context it comes in:

When to use Ruby symbols?

Well, this might be the one million dollars question, and that’s initially why i wrote this post for. You also might be wondering, why have Matz chosen to give us this low level introspection in the language by allowing me to work with the interpreter stuff?

The answer is divided in 2 parts:

1- Efficiency. 2- Metaprogramming(reflection).

Efficiency

We will talk about efficiency at first place,so let’s check this snippet of code:

The snippet of code above is really costive, in terms of memory and efficiency:
1-Comparing 2 strings is costive, specially when the 2 strings are long.
2-Reserving “changeable” amount of memory, 16 bytes in our case to instantiate “Khaled alhabache”.
3-The GC would have to clean this “Khaled alhabache” later on.

What about doing :

Now what we did is:
1-Comparing 2 integers(the value of a symbol is integer) which is cheaper.
2-Reserving memory 4 bytes for :”Khaled alhabache” symbol, cause a symbol is an integer finally.
3-The GC would not have to clean this :”Khaled alhabache” symbol, cause symbols don’t get deleted till program exits.

So use symbols as much as you can, and avoid using stings as much as you can, but take extra care of defining thousands of symbols, cause as mentioned: symbols don’t get deleted till program exits, and thus they stick in memory.

Metaprogramming and symbols

Well working with metaprogramming in Ruby is really nice, you can do something like:

Without symbols, you would never be able to use reflection techniques like ‘send’, otherwise how can you invoke methods dynamically?, also without symbols, you would never be able to use introspection techniques like ‘respond_to?’

Update, a respond to readers comments:
It’s true that you can do something like :

But what’s happening is that Ruby is casting it for you, but why to reserve extra memory to send it as a string?

For guys who are objecting on memory efficiency with symbols, I strongly recommend reading this post also.

I hope I could help you understand what Ruby symbols are and why they are used for, specially of you who are coming from other programing backgrounds.


Related articles