Конкатенация строк и интерполяция в Ruby

Я только начинаю изучать Ruby (программирование в первый раз), и у меня есть основной синтаксический вопрос в отношении переменных и различных способов написания кода.

Крис Пайн & quot; Учиться программировать & quot; научил меня писать основную программу, как это ...

<code>num_cars_again= 2
puts 'I own ' + num_cars_again.to_s + ' cars.'
</code>

Это хорошо, но потом я наткнулся на учебник на ruby.learncodethehardway.com, и меня научили писать точно такую же программу, как эта ...

<code>num_cars= 2
puts "I own #{num_cars} cars."
</code>

Они оба выводят одно и то же, но, очевидно, вариант 2 - гораздо более короткий способ сделать это.

Есть ли какая-то конкретная причина, почему я должен использовать один формат поверх другого?

 sameers26 июн. 2013 г., 23:00
Есть больше вариантов, которые обсуждаются наstackoverflow.com/questions/377768/…
 Andrew Grimm10 апр. 2012 г., 01:47
Тьфу. Я ненавижу, как часто книги для начинающих учат вас неестественному способу делать вещи, по крайней мере, не говоря вам, что существуют альтернативы. +1 за законный вопрос, за который не проголосовали.

Ответы на вопрос(4)

и конкатенация имеют свои сильные и слабые стороны. Ниже я дал эталон, который ясно показывает, где использовать конкатенацию и где использовать интерполяцию.

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)
--------------------------------------------------

Conclusion

Если строки уже определены и уверены, что они никогда не будут равны нулю, используйте конкатенацию, иначе используйте интерполяцию. Используйте соответствующую, которая приведет к лучшей производительности, чем та, которую легко сделать отступом.

 09 дек. 2014 г., 22:13
какую версию Ruby вы использовали?
 12 мар. 2018 г., 10:23
Я попробовал это в ruby 2.5.0 иinterpolation быстрее чемconcatenation в обоих случаях. Я не могу вставить результаты из-за ограничения длины комментария, но вы можете попробовать сами.

я обнаружил, что с помощью конкатенации (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

В предположении я бы сказал, что интерполяция генерирует временную строку, поэтому она медленнее.

Решение Вопроса

когда TIMTOWTDI (есть несколько способов сделать это), вы должны искать плюсы и минусы. Использование & quot; интерполяции строк & quot; (второе) вместо «конкатенации строк» (первый):

Pros:

Is less typing Automatically calls to_s for you More idiomatic within the Ruby community Faster to accomplish during runtime

Cons:

Automatically calls 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) Requires you to use " 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)
 09 апр. 2012 г., 18:54
Мое предположение: потому что"attaching strings together using a well-known operator" это простая концепция для нового программиста, чем"use a custom syntax to evaluate arbitrary code, call to_s on the result, and inject it into the middle of a string", При изучении любой новой вещи часто встречаются варианты «простого для понимания способа». по сравнению с тем, как это делают профессионалы.
 09 апр. 2012 г., 18:51
если вы заботитесь о тестах, это также быстрее:try me in REPL
 09 апр. 2012 г., 18:51
Не забывайте, что это быстрее. аспект. Конкатенация строк в этом примере должна создать всего 3 строки, а интерполяция строк - только одну.
 Jeff H.09 апр. 2012 г., 18:52
Большое спасибо за ответы. Быстрый вопрос. Почему книга Криса Пайна научит тому, как это сделать? Может быть, новичку лучше научиться делать это дольше? Его книга говорит, что в большинстве случаев время ленивее = лучше, поэтому мне интересно, если, может быть, по какой-то причине (поскольку я только учусь), мне следует продолжать делать это по-своему или двигаться вперед с этим лучшим способом. Есть идеи?
 09 сент. 2014 г., 05:30
Я знаю, что опоздал к этой дискуссии, но есть две основные причины, почему я сделал это так, как сделал. Во-первых, по причинам, которые приводит Фрогз: я пытался сделать это как можно проще, используя понятия, которые они уже знали. Я даже не описывал строки в двойных кавычках в первом издании! Последнее, что кто-то хочет при обучении программированию, - это шесть различных синтаксисов для создания строк. Во-вторых, из-за неявногоto_s, Да, для тех из нас, кто понимает типы и преобразования, это удобно. Но для нового программиста очень важно понимать эти концепции.

@ user1181898 - ИМХО, это потому, что легче увидеть, что происходит. строковая интерполяция автоматически вызывает to_s для вас. Как новичок, вы должны видеть, что происходит "под капотом". так что вы изучаете концепцию, а не просто наизусть.

Думайте об этом как об обучении математике. Вы изучаете "длинный" путь, чтобы понять концепции, чтобы вы могли использовать ярлыки, когда вы действительно знаете, что делаете. Я говорю по своему опыту, потому что я еще не настолько продвинут в Ruby, но я сделал достаточно ошибок, чтобы посоветовать людям, что не следует делать. Надеюсь это поможет.

 Jeff H.09 апр. 2012 г., 19:13
Большое спасибо, это делает!

Ваш ответ на вопрос