Ruby(初回プログラミング))を学び始めたばかりで、変数やコードのさまざまな作成方法に関する基本的な構文上の質問があります。
クリス・パインの「プログラムを学ぶ」は、このような基本的なプログラムを書くことを教えてくれました...
num_cars_again= 2
puts 'I own ' + num_cars_again.to_s + ' cars.'
これは問題ありませんが、Ruby.learncodethehardway.comのチュートリアルを偶然見つけて、このようなプログラムとまったく同じプログラムを書くように教えられました...
num_cars= 2
puts "I own #{num_cars} cars."
どちらも同じ結果を出力しますが、明らかにオプション2はそれを行うためのはるかに短い方法です。
あるフォーマットを他のフォーマットよりも使用する必要がある特別な理由はありますか?
TIMTOWTDI(それを行う方法は複数あります)のたびに、長所と短所を探す必要があります。 「文字列連結」(1番目)の代わりに「文字列補間」(2番目)を使用します。
長所:
to_s
を自動的に呼び出します短所:
to_s
を呼び出します(文字列があると思ったかもしれませんが、to_s
表現は望んでいるものではなく、文字列ではないという事実を隠しています)"
の代わりに'
を使用して文字列を区切る必要があります(おそらく'
を使用する習慣があるか、それを使用して以前に文字列を入力し、後で文字列補間を使用する必要があります) )補間と連結の両方には、独自の長所と短所があります。以下に、連結を使用する場所と補間を使用する場所を明確に示すベンチマークを示しました。
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
以下はベンチマークの結果です
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)
--------------------------------------------------
結論
文字列がすでに定義されていて、決してnilにならない場合は連結を使用し、そうでない場合は補間を使用します。インデントしやすい文字列よりもパフォーマンスが向上する適切な文字列を使用します。
@ user1181898-私見、それは何が起こっているのかを見るのが簡単だからです。 @Phrogzのポイントでは、文字列補間は自動的にto_sを呼び出します。初心者として、あなたは「フードの下で」何が起こっているのかを見る必要があります。
数学を学ぶようなものだと考えてください。コンセプトを理解するために「長い」方法を学び、実際に自分が何をしているのかを理解したら、ショートカットを取ることができます。私は経験から話していますb/c私はRubyでまだ高度ではありませんが、何をすべきでないかを人々にアドバイスするために十分な間違いを犯しました。
文字列をバッファとして使用している場合、連結(String#concat
)より高速に。
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
結果:
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
推測では、補間は一時的な文字列を生成すると言うので、それが遅い理由です。