Ruby 3.0 Added name Method For Symbols
September 11, 2020
In Ruby, symbols are immutable and strings are mutable.
:football.frozen?
#=> true
:football.to_s.frozen?
#=> false
# Ruby 3.0.0
:football.name.frozen?
#=> true
If we define a symbol once, then a single memory location is referred everywhere.
In short, symbols help us to reduce memory allocations.
Rubyists use symbols and strings interchangeably in many places.
Let's see an example:
def game(sport)
3.times do
s = sport
puts s + " is my fav game!"
puts s.object_id
end
end
game(:football)
#=> NoMethodError (undefined method `+' for :football:Symbol)
To fix the above error, we can use to_s
method to convert the symbol :football
to a string "football"
.
Let's fix the above example:
def game(sport)
3.times do
s = sport.to_s
puts s + " is my fav game!"
puts s.object_id
end
end
game(:football)
# output
#=> football is my fav game!
#=> 240
#=> football is my fav game!
#=> 260
#=> football is my fav game!
#=> 280
Good that we fixed the error but there is a memory allocation overhead.
By using to_s
for a symbol :football
within a loop, we unnecessarily created three new mutable strings and Ruby internally allocated separate memory locations as indicated by object_id
(240, 260, 280).
Before Ruby 3.0, we can handle this memory allocation issue as below: (mark the -sport.to_s
line)
def game(sport)
3.times do
s = -sport.to_s
puts s + " is my fav game!"
puts s.object_id
end
end
game(:football)
But using -@
is not very readable and it does not offer a consistent syntax either.
For example:
10.to_s
#=> "10"
# unexpected result
-10.to_s
#=> "-10"
-10.to_s.frozen?
#=> false
# inconsistent syntax to get desired result
-(10).to_s
#=> "10"
-(10).to_s.frozen?
#=> true
-true.to_s
#=> "true"
# error while chaining methods
-true.to_s.frozen?
-(true).to_s.frozen?
#=> NoMethodError (undefined method `-@' for true:TrueClass)
Finally, Ruby 3.0.0 has introduced Symbol#name
method which will return the name of the symbol as a frozen string.
This will significantly reduce memory allocations for projects in Rails.
Let's see how it helps in minimizing memory allocation in our example:
def game(sport)
3.times do
s = sport.to_s
puts s + " is my fav game!"
puts s.object_id
end
end
# output
#=> football is my fav game!
#=> 300
#=> football is my fav game!
#=> 300
#=> football is my fav game!
#=> 300
As we can see above, Ruby did not create a new string each time rather it just created the string in memory once and refers every time it is used.
However it is still worth debating whether Ruby should have introduced another method name
for symbols or should have changed behavior of existing Symbol#to_s
method to return a frozen string.
If we want existing Symbol#to_s
method to return frozen strings by default, we can use symbol-fstring gem as of now.
This is the link to the relevant discussion.
info@scriptday.com