#---Symbols---
You graduate from a Ruby beginner to a Ruby advanced beginner when you grok Symbols.
A symbol is a lightweight string alternative. It’s an immutable object that’s often used as an identifier.
Symbols are similar to strings, but they are more efficient in terms of memory and performance because they are stored in a single memory location and are not duplicated.
They also don’t have any of the many modification/manipulation methods that strings have, because they’re only used as identifiers and not as data.
There are many ways to create symbols.
Using a colon (:
) followed by the symbol name:
x = :a_symbol
p x # => :a_symbol
p x.class # => Symbol
Using the to_sym
or its alias intern
method on a
string:
## a symbol with spaces
p 'an identifier'.to_sym # => :"an identifier"
You can create an array of symbols with %i()
, just
like how you’d create an array of strings with %w()
:
p %w(one two three) # => ["one", "two", "three"]
p %i(one two three) # => [:one, :two, :three]
In a Ruby program, the same string used in different variables are stored separately:
str1, str2 = 'foo', 'foo'
p str1.object_id # => 148008
p str2.object_id # => 148016
But if you save the value as a symbol, Ruby will recognize that the value is same and use only one object no matter how many times you use the same value throughout the program:
sym1, sym2 = :foo, :foo
p sym1.object_id # => 58609932
p sym2.object_id # => 58609932
Symbols are also lightweight because they don’t have any of the string manipulation methods:
p str1.concat(str2) # => "foofoo"
p sym1.concat(sym2) rescue nil
## => 💥 blows up with NoMethodError without `rescue nil`
This means using symbols as identifiers in your code will make your program performant and memory efficient.
A string can be converted to a symbol with to_sym
.
A symbol can be converted to a string with to_s
. But
in a string interpolation, you can use a symbol as-is:
p "Hi #{sym1}" # => "Hi foo"
In a hash, use symbols instead of strings to identify keys:
h1 = {:a => 'aa', :b => 'bb'}
A shorter, better way of writing the same hash:
h1 = {a: 'aa', b: 'bb'}
Use symbols for method names instead of strings:
define_method(:a_dynamic_method) { 42 }
p a_dynamic_method # => 42
Use symbols for variables that are names for things:
user_input = :red
STATUS_GREEN = :green
action = user_input == STATUS_GREEN ? :go : :stop
p action # => :stop
.