Ruby Symbols

Symbols in ruby are like labels. They are also strings, however unlike ruby string objects which are mutable (modifiable post instantiation),  symbols are immutable strings and belong to the Symbol class. They are used where immutability, performance and space are key and the richness of the string class is not required.

There are many ways to instantiate a symbol object.

:ruby and :”ruby” are the same literal.

%s{ruby}

:’United States of America’ – quotes should be used when the symbol has spaces

x = “string”

symbol = :”#{x}”

The ‘intern’ or ‘to_sym’ methods can be used to convert a String object to a Symbol object. With the methods ‘to_s’ and its alias ‘id2name’: a Symbol object can be converted back to a String.

var = “string”

sym = var.intern

sym = var.to_sym

var = sym.to_s

var = sym.id2name

Symbols enable us to use a single memory location to represent a literal, thus saving memory in the long run. A String would occupy a different memory location each time it is instantiated, which means two strings can hold the same content yet be completely distinct objects and use up multiple amounts of space. This becomes an issue especially if we want to use the same literal repeatedly during the course of a program. With symbols, distinct symbol objects will always have different content. Different strings with the same content will all be converted to the same Symbol object.  Therefore symbols are the better choice for unique identifiers.

Eg: if we want to use the word ‘ruby’ and create assignments as string objects;

gem = “ruby”

rails_language = “ruby”

calling object_id on each of the variables shows that they are pointing to different  “ruby” string objects.  When assignments are created using the word ‘ruby’ as a symbol;

gem = :ruby

rails_language = :ruby

they point to the same ruby object.

symbols1

Using ‘intern’ and ‘to_s’ methods to demonstrate that different string objects with the same content will convert to the same symbol object (as shown in The Ruby Programming Language).  This is covered above, however, I present it here since it’s pretty neat to use the ‘intern’ and ‘to_s’ methods in the proof.

symbols2

In addition to economies of storage, symbols also offer better performance when used as unique identifiers. This is due to the ruby interpreter. The way the ruby interpreter works is by storing symbols referencing the names of all the classes, methods and variables that have been defined, in a table. If it needs to refer to a method name for example, it does so by its position in the table. This way, only integer operations are carried out and string operations are avoided. Therefore, with a unique identifier for example, it is much faster to carry out comparisons etc. if they are defined as symbols than if they were string objects.

Although the Symbol class is a computationally economical option than String class, some String class methods such as length, size, the comparison operators and the [] and =~ operators are defined in the Symbol class too, enabling the use of symbols to a certain extent as strings. This makes a symbol an immutable string which is not garbage-collected.

Using irb, we can call the methods ‘all_symbols.size’ on Symbol and find out how many symbol objects already exist in ruby. When we define a variable ‘my_symbol’ for instance, that variable is stored as a symbol in the symbol table and if we call ‘all_symbols.size’ again on Symbol we notice that the size has increased by 1 as shown below.

symbols3

Advertisement