I am just starting to learn Ruby (first time programming), and have a basic syntactical question with regards to variables, and various ways of writing code.
Chris
Here is a full benchmark which also compares Kernel#format
and String#+
as it's all methods for construction dynamic string in ruby that I know
Whenever TIMTOWTDI (there is more than one way to do it), you should look for the pros and cons. Using "string interpolation" (the second) instead of "string concatenation" (the first):
Pros:
to_s
for youCons:
to_s
for you (maybe you thought you had a string, and the to_s
representation is not what you wanted, and hides the fact that it wasn't a string)"
to delimit your string instead of '
(perhaps you have a habit of using '
, or you previously typed a string using that and only later needed to use string interpolation)@user1181898 - IMHO, it's because it's easier to see what's happening. To @Phrogz's point, string interpolation automatically calls the to_s for you. As a beginner, you need to see what's happening "under the hood" so that you learn the concept as opposed to just learning by rote.
Think of it like learning mathematics. You learn the "long" way in order to understand the concepts so that you can take shortcuts once you actually know what you are doing. I speak from experience b/c I'm not that advanced in Ruby yet, but I've made enough mistakes to advise people on what not to do. Hope this helps.
Both interpolation and concatination has its own strength and weakness. Below I gave a benchmark which clearly demonstrates where to use concatination and where to use interpolation.
require 'benchmark'
iterations = 1_00_000
firstname = 'soundarapandian'
middlename = 'rathinasamy'
lastname = 'arumugam'
puts 'With dynamic new strings'
puts '===================================================='
5.times do
Benchmark.bm(10) do |benchmark|
benchmark.report('concatination') do
iterations.times do
'Mr. ' + firstname + middlename + lastname + ' aka soundar'
end
end
benchmark.report('interpolaton') do
iterations.times do
"Mr. #{firstname} #{middlename} #{lastname} aka soundar"
end
end
end
puts '--------------------------------------------------'
end
puts 'With predefined strings'
puts '===================================================='
5.times do
Benchmark.bm(10) do |benchmark|
benchmark.report('concatination') do
iterations.times do
firstname + middlename + lastname
end
end
benchmark.report('interpolaton') do
iterations.times do
"#{firstname} #{middlename} #{lastname}"
end
end
end
puts '--------------------------------------------------'
end
And below is the Benchmark result
Without predefined strings
====================================================
user system total real
concatination 0.170000 0.000000 0.170000 ( 0.165821)
interpolaton 0.130000 0.010000 0.140000 ( 0.133665)
--------------------------------------------------
user system total real
concatination 0.180000 0.000000 0.180000 ( 0.180410)
interpolaton 0.120000 0.000000 0.120000 ( 0.125051)
--------------------------------------------------
user system total real
concatination 0.140000 0.000000 0.140000 ( 0.134256)
interpolaton 0.110000 0.000000 0.110000 ( 0.111427)
--------------------------------------------------
user system total real
concatination 0.130000 0.000000 0.130000 ( 0.132047)
interpolaton 0.120000 0.000000 0.120000 ( 0.120443)
--------------------------------------------------
user system total real
concatination 0.170000 0.000000 0.170000 ( 0.170394)
interpolaton 0.150000 0.000000 0.150000 ( 0.149601)
--------------------------------------------------
With predefined strings
====================================================
user system total real
concatination 0.070000 0.000000 0.070000 ( 0.067735)
interpolaton 0.100000 0.000000 0.100000 ( 0.099335)
--------------------------------------------------
user system total real
concatination 0.060000 0.000000 0.060000 ( 0.061955)
interpolaton 0.130000 0.000000 0.130000 ( 0.127011)
--------------------------------------------------
user system total real
concatination 0.090000 0.000000 0.090000 ( 0.092136)
interpolaton 0.110000 0.000000 0.110000 ( 0.110224)
--------------------------------------------------
user system total real
concatination 0.080000 0.000000 0.080000 ( 0.077587)
interpolaton 0.110000 0.000000 0.110000 ( 0.112975)
--------------------------------------------------
user system total real
concatination 0.090000 0.000000 0.090000 ( 0.088154)
interpolaton 0.140000 0.000000 0.140000 ( 0.135349)
--------------------------------------------------
Conclusion
If strings already defined and sure they will never be nil use concatination else use interpolation.Use appropriate one which will result in better performance than one which is easy to indent.
If you are using a string as a buffer, I found that using concatenation (String#concat
) to be faster.
require 'benchmark/ips'
puts "Ruby #{RUBY_VERSION} at #{Time.now}"
puts
firstname = 'soundarapandian'
middlename = 'rathinasamy'
lastname = 'arumugam'
Benchmark.ips do |x|
x.report("String\#<<") do |i|
buffer = String.new
while (i -= 1) > 0
buffer << 'Mr. ' << firstname << middlename << lastname << ' aka soundar'
end
end
x.report("String interpolate") do |i|
buffer = String.new
while (i -= 1) > 0
buffer << "Mr. #{firstname} #{middlename} #{lastname} aka soundar"
end
end
x.compare!
end
Results:
Ruby 2.3.1 at 2016-11-15 15:03:57 +1300
Warming up --------------------------------------
String#<< 230.615k i/100ms
String interpolate 234.274k i/100ms
Calculating -------------------------------------
String#<< 2.345M (± 7.2%) i/s - 11.761M in 5.041164s
String interpolate 1.242M (± 5.4%) i/s - 6.325M in 5.108324s
Comparison:
String#<<: 2344530.4 i/s
String interpolate: 1241784.9 i/s - 1.89x slower
At a guess, I'd say that interpolation generates a temporary string which is why it's slower.