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 🙂
Great work Jesus, i find your posts helpful & enjoyable 🙂
Thank you Dmytro! 🙂
In the method_missing example, is it necessary to call
super(args)
? I thought justsuper
would automatically pass the same args.Hi Mike,
you are correct, it’s not necessary & it works as you say 🙂