Why is the shovel operator (<<) preferred over plus-equals (+=) when building a string in Ruby?
Proof:
a = 'foo'
a.object_id #=> 2154889340
a << 'bar'
a.object_id #=> 2154889340
a += 'quux'
a.object_id #=> 2154742560
So <<
alters the original string rather than creating a new one. The reason for this is that in ruby a += b
is syntactic shorthand for a = a + b
(the same goes for the other <op>=
operators) which is an assignment. On the other hand <<
is an alias of concat()
which alters the receiver in-place.
Performance proof:
#!/usr/bin/env ruby
require 'benchmark'
Benchmark.bmbm do |x|
x.report('+= :') do
s = ""
10000.times { s += "something " }
end
x.report('<< :') do
s = ""
10000.times { s << "something " }
end
end
# Rehearsal ----------------------------------------
# += : 0.450000 0.010000 0.460000 ( 0.465936)
# << : 0.010000 0.000000 0.010000 ( 0.009451)
# ------------------------------- total: 0.470000sec
#
# user system total real
# += : 0.270000 0.010000 0.280000 ( 0.277945)
# << : 0.000000 0.000000 0.000000 ( 0.003043)
A friend who is learning Ruby as his first programming language asked me this same question while going through Strings in Ruby on the Ruby Koans series. I explained it to him using the following analogy;
You have a glass of water that is half full and you need to refill your glass.
First way you do it by taking a new glass, filling it halfway with water from a tap and then using this second half-full glass to refill your drinking glass. You do this every time you need to refill your glass.
The second way you take your half full glass and just refill it with water straight from the tap.
At the end of the day, you would have more glasses to clean if you choose to pick a new glass every time you needed to refill your glass.
The same applies to the shovel operator and the plus equal operator. Plus equal operator picks a new 'glass' every time it needs to refill its glass while the shovel operator just takes the same glass and refills it. At the end of the day more 'glass' collection for the Plus equal operator.