Я только начинаю изучать 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 (существует более одного способа сделать это), вы должны искать плюсы и минусы. Использование "интерполяции строк" (второе) вместо "конкатенации строк" (первое):
Плюсы:
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 для вас. Как начинающему, вам нужно видеть, что происходит "под капотом", чтобы вы усвоили концепцию, а не просто заучивали.
Подумайте об этом, как при изучении математики. Вы учитесь "долгим" путем, чтобы понять концепции, чтобы потом, когда вы действительно знаете, что делаете, вы могли использовать короткие пути. Я говорю на своем опыте, потому что я еще не настолько продвинулся в Ruby, но я сделал достаточно ошибок, чтобы советовать людям, чего не следует делать. Надеюсь, это поможет.
Если вы используете строку в качестве буфера, я обнаружил, что с помощью конкатенации (строка#функция 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
Думаю, я'd не сказать, что интерполяция создает временную строку, которая является, почему это'ы медленнее.