web-dev-qa-db-fra.com

Concaténation de chaînes vs interpolation dans Ruby

Je commence tout juste à apprendre Ruby (première programmation)) et j'ai une question syntaxique de base en ce qui concerne les variables et les différentes façons d'écrire du code.

"Learn to Program" de Chris Pine m'a appris à écrire un programme de base comme celui-ci ...

num_cars_again= 2
puts 'I own ' + num_cars_again.to_s + ' cars.'

C'est bien, mais ensuite je suis tombé sur le tutoriel sur Ruby.learncodethehardway.com, et j'ai appris à écrire le même programme exact comme celui-ci ...

num_cars= 2
puts "I own #{num_cars} cars."

Ils produisent tous deux la même chose, mais évidemment, l'option 2 est un moyen beaucoup plus court de le faire.

Y a-t-il une raison particulière pour laquelle je devrais utiliser un format plutôt qu'un autre?

72
Jeff H.

Chaque fois que TIMTOWTDI (il y a plus d'une façon de le faire), vous devriez rechercher les avantages et les inconvénients. Utiliser "interpolation de chaîne" (la seconde) au lieu de "concaténation de chaîne" (la première):

Avantages:

  • Est moins tapant
  • Appelle automatiquement to_s pour toi
  • Plus idiomatique au sein de la communauté Ruby
  • Plus rapide à accomplir pendant l'exécution

Inconvénients:

  • Appelle automatiquement to_s pour vous (vous pensiez peut-être que vous aviez une chaîne, et le to_s la représentation n'est pas ce que vous vouliez, et cache le fait que ce n'était pas une chaîne)
  • Vous oblige à utiliser " pour délimiter votre chaîne au lieu de ' (vous avez peut-être l'habitude d'utiliser ', ou vous avez déjà tapé une chaîne à l'aide de cela et vous n'avez eu besoin que plus tard d'utiliser l'interpolation de chaîne)
71
Phrogz

L'interpolation et la concatination ont chacune leur force et leur faiblesse. Ci-dessous, j'ai donné une référence qui montre clairement où utiliser la concatination et où utiliser l'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

Et ci-dessous est le résultat de référence

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

Si les chaînes sont déjà définies et sûres qu'elles ne seront jamais nulles, utilisez la concatination, sinon utilisez l'interpolation.

8

@ user1181898 - À mon humble avis, c'est parce qu'il est plus facile de voir ce qui se passe. Au point de @ Phrogz, l'interpolation de chaînes appelle automatiquement les to_s pour vous. En tant que débutant, vous devez voir ce qui se passe "sous le capot" afin que vous appreniez le concept plutôt que d'apprendre par cœur.

Pensez-y comme à l'apprentissage des mathématiques. Vous apprenez le "long" chemin afin de comprendre les concepts afin de pouvoir prendre des raccourcis une fois que vous savez réellement ce que vous faites. Je parle d'expérience b/c, je ne suis pas très avancé en Ruby pour l'instant, mais j'ai fait suffisamment d'erreurs pour conseiller les gens sur ce qu'il ne faut pas faire. J'espère que cela vous aidera.

4
Martin Graham

Si vous utilisez une chaîne comme tampon, j'ai trouvé que l'utilisation de la concaténation (String#concat) pour être plus rapide.

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

Résultats:

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

À une supposition, je dirais que l'interpolation génère une chaîne temporaire, c'est pourquoi elle est plus lente.

2
ioquatix