What Are Ruby Symbols & How Do They Work?

A symbol looks like this:

:testing

Some people confuse symbols with variables, but they have nothing to do with variables…

a symbol is a lot more like a string.

So what are the differences between Ruby symbols & strings?

Strings are used to work with data.

Symbols are identifiers.

That’s the main difference:

Symbols are not just another kind of string, they have a different purpose.

When to Use Symbols

One of the most common uses for symbols is to represent method & instance variable names.

Example:

attr_reader :title

The :title after attr_reader is a symbol that represents the @title instance variable.

You can also use symbols as hash keys.

Example:

hash = {a: 1, b: 2, c: 3}

The benefits?

Symbols look better, they are immutable & if you benchmark string keys vs symbols keys you will find that string keys are about 1.70x slower.

By immutable I mean that every symbol is unique, and it can’t be changed:

:rubyguides.object_id
# 437768

:rubyguides.object_id
# 437768

These two symbols are the same object because they have the same object id.

Symbols can be used in metaprogramming methods like send:

[1,2,3].send(:first)

In Summary:

You should use symbols as names or labels for things (like methods) & use strings when you care more about the data (individual characters).

Converting Between Strings & Symbols

You can convert a symbol into a string when necessary.

Why would you want to do that?

Because symbols only have a subset of the methods that a String has.

And symbols can’t be changed, so if you want to work with the individual characters of the symbol then you want a string.

You can do this using the to_s method.

For example, when using method_missing you get the name of the missing method as a symbol. You may want to check if this method name matches a certain pattern (like ending in ?).

Example:

def method_missing(method_name, *args, &block)
  if method_name.to_s[-1] == "?"
    # do something
  else
    super
  end
end

You can also convert a string object into a symbol object.

The method to do this is String#to_sym:

"rubyguides".to_sym

:rubyguides

Creating An Array Of Symbols

If you want to create an array of symbols you can use this code:

symbols = %i(a b c)

[:a, :b, :c]

This saves you from having to type the colons & the commas.

Similar to the string version %w:

strings = %w(a b c)

["a", "b", "c"]

Ruby Symbols Video

Symbol GC (Advanced)

Another interesting fact about symbols is that there are different types.

The reason is that symbols were not garbage collected before Ruby 2.2, which means that they where not cleaned up from memory when no longer needed like regular Ruby objects (strings, hashes, arrays…).

You can see an example here:

p Symbol.all_symbols.size
# 2443

('aa'..'aj').map(&:to_sym)

GC.start
p Symbol.all_symbols.size
# 2453

You will notice that the total count of symbols increases by 10, just like you would expect since we are creating 10 new symbols.

But since Ruby 2.2 these symbols are removed from memory because they are just temporary & not being used by something else in this code.

If you try this code on a version of Ruby that has Symbol GC enabled both symbol counts will be the same.

Some symbols will never be removed from memory, these are called “immortal symbols”.

You can count them using the ObjectSpace module:

require 'objspace'

ObjectSpace.count_symbols

{
  :mortal_dynamic_symbol=>3,
  :immortal_dynamic_symbol=>5,
  :immortal_static_symbol=>3663,
  :immortal_symbol=>3668
}

Notice that symbols created directly, like :a1 will automatically become immortal symbols. Creating a new method will also create an immortal_static_symbol to go with it.

So where do mortal symbols come from?

From strings converted into symbols with the to_sym method.

You can check this yourself using ObjectSpace.count_symbols.

And if you are wondering what’s an immortal_dynamic_symbol, it’s a symbol that has been promoted from mortal to immortal. This can happen when you create a method with the name of a mortal symbol.

Summary

On this article you learned:

  • Symbols are immutable
  • Symbols are not pointer to values, they are values themselves
  • Strings are for data & symbols are for identity
  • How to convert between strings & symbols
  • Symbol GC was introduced in Ruby 2.2 to clean up temporary symbols

Hope you learned something new!

Please share this post so it can reach more people 🙂

4 thoughts on “What Are Ruby Symbols & How Do They Work?”

  1. In the method_missing example, is it necessary to call super(args)? I thought just super would automatically pass the same args.

Comments are closed.