String concatenation vs. interpolation in Ruby

前端 未结 5 1099
北海茫月
北海茫月 2020-11-27 16:06

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

相关标签:
5条回答
  • 2020-11-27 16:21

    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

    0 讨论(0)
  • 2020-11-27 16:23

    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:

    • 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)
    0 讨论(0)
  • 2020-11-27 16:24

    @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.

    0 讨论(0)
  • 2020-11-27 16:29

    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.

    0 讨论(0)
  • 2020-11-27 16:29

    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.

    0 讨论(0)
提交回复
热议问题