tundal45@wordpress:~$

>puts "Hello, World!"

Ruby: Shovel vs. Plus Equals

with 12 comments

This is going to be first of what I hope to be many blog posts documenting my foray into Ruby programming. Foray might be a bad choice of word given that this is not my first attempt at learning the language. However, the approach that I am taking this time around is more active than my previous attempts so I am hopeful. Like any other endeavor, this too has a goal & a specific one at that – being able to build a foundation in Ruby in time for Lone Star Ruby Conference at the end of August.

The approach this time is to follow Mike Clark‘s advice and build tests as I delve into different features of Ruby while reading The Well Grounded Rubyist by David A. Black.

The reason I am optimistic about this approach is because I am currently working through the wonderful Ruby Koans created by EdgeCase. Ruby Koans was what introduced me to Mike Clark’s approach on learning different facets of Ruby. This is a great starting point for anyone who is new to Ruby as it introduces both the core concepts or Ruby while introducing the idea of testing. Since we are not writing code, it is not test-first-development but more of an inquiry into the ruby interpreter through test cases. The best part about Ruby Koans so far is the question that are posed that forces you to move away from the hows that the tests focus on to more of the whys. I am going to focus on one such whys on this post.

The question posed in one of the Koans was in regards to String modification. The tests were for the shovel (<<) & plus equals (+=) operators. The question was:

“Ruby programmers tend to favor the shovel operator (<<) over the plus equals operator (+=) when building up strings. Why?”

At first, I did not pay attention to this & was about to move to the next failing test. However, since I wanted to do proper justice to my learning experience, I decided to think a little bit about the the two operators in relation to the question being posed. My gut feeling told me that it probably had to do with the fact that the shovel (<<) operator modifies the actual object while the plus equals (+=) operator created a new object altogether.

Of course, I was afraid of being wrong and wanted to verify this. I was about to fire up IRB to test it out when I remembered Mike Clark’s approach to learning and thought I should write a test to see if what I was thinking was the answer was true. So, I decided to write a quick test:
require ‘test/unit’

class StringTest < Test::Unit::TestCase

  def test_plus_equals_creates_new_object
    original_string = "Hello, "
    hi = original_string
    assert_equal original_string.object_id, hi.object_id
    there = "World"
    hi += there
    assert_not_equal original_string.object_id, hi.object_id
  end

  def test_shovel_does_not_create_new_object
    original_string = "Hello, "
    hi = original_string
    assert_equal original_string.object_id, hi.object_id
    there = "World"
    hi << there
    assert_equal original_string.object_id, hi.object_id
  end
end

The test proved my initial hunch. I was going to leave it at that but then I remembered that Array also use both operators. So I wrote another test to verify that the behavior is the same for Arrays:

require 'test/unit'

class ArrayTest < Test::Unit::TestCase

  def test_plus_equals_creates_new_object
    original_string = ["Hello"]
    hi = original_string
    assert_equal original_string.object_id, hi.object_id
    there = ["World"]
    hi += there
    assert_not_equal original_string.object_id, hi.object_id
  end

  def test_shovel_does_not_create_new_object
    original_string = ["Hello"]
    hi = original_string
    assert_equal original_string.object_id, hi.object_id
    there = ["World"]
    hi << there
    assert_equal original_string.object_id, hi.object_id
  end

end

So long story short, the reason why Ruby programmers prefer the shovel operator (<<) over the plus equals (+=) operator when building strings is to avoid creating multiple objects during the process. If there are subtleties that I am missing or if I am completely wrong, I would love to hear from people and improve upon what I have learned so far.

UPDATE: Thanks to @i82much for telling me how to embed code in wordpress.

UPDATE 2: Thanks again to @i82much, you can find out how to have source code displayed for different languages here

About these ads

Written by tundal45

July 10, 2010 at 12:42 am

Posted in ruby

Tagged with , , ,

12 Responses

Subscribe to comments with RSS.

  1. If the goal is to build up a large string, there’s a third way that’s also idiomatic ruby is on par with the shovel operator in terms of performance. I’m talking about building an array, and then using Array#join.

    Here’s a script that demonstrates what I’m talking about:


    require 'benchmark'

    N = 50_000

    Benchmark.bm do |bench|
    bench.report "shovel" do
    (0..N).inject("") {|memo,n| memo << "this is line #{n}\n" }
    end

    bench.report "plus-equals" do
    (0..N).inject("") {|memo,n| memo += "this is line #{n}\n" }
    end

    bench.report "join" do
    (0..N).map {|n| "this is line #{n}" }.join("\n")
    end
    end

    The output speaks for itself:


    phiggins@lihnucks ~/test $ ruby test_string_concat.rb
    user system total real
    shovel 0.090000 0.000000 0.090000 ( 0.085974)
    plus-equals 16.250000 0.130000 16.380000 ( 18.514102)
    join 0.090000 0.000000 0.090000 ( 0.088373)

    pete

    July 10, 2010 at 9:51 pm

    • Thanks for reminding me about benchmark Pete. I had learned about that somewhere (possibly in Beginning Ruby by Peter Cooper) before and completely forgotten about it. That is definitely useful. Thanks!

      tundal45

      July 10, 2010 at 10:25 pm

  2. For syntax highlighting, try

    var i = 0;

    If that didn’t come out right, it’s

    left bracket sourcecode language=”javascript” right bracket code left bracket slash sourcecode right bracket

    i82much

    July 13, 2010 at 4:05 am

    • Thanks for teaching me how to have syntax highlighting on WordPress. This makes it a lot better when people don’t have to open the gists separately.

      tundal45

      July 17, 2010 at 3:09 pm

  3. Thanks for posting this! I had the exact same questions while doing the string koan and wanted to see if someone else had already verified them. :)

    Mike Murray

    July 17, 2010 at 5:01 am

    • I am glad you found the post useful Mike. I am hoping to get more traction in my learning so hopefully I will continue to come across interesting things I can blog about & learn more from people’s feedback.

      tundal45

      July 17, 2010 at 3:08 pm

  4. I just confirmed this, too. I made some benchmarks and plots: http://www.alecjacobson.com/weblog/?p=1344. Can’t think of any reason why this implementation makes sense…

    Alec Jacobson

    September 8, 2010 at 5:43 pm

  5. One downside of using the shovel operator to concatenate strings is that it doesn’t make a Rails model dirty. For example:

    e = Employee.first
    e.name << "sadf"
    e.name_changed? # returns false
    e.changed? # returns false

    Since the shovel operator doesn't create a new instance of the string, Rails doesn't seem to know that anything changed.

    Jon Kruger

    November 9, 2010 at 7:52 pm

    • Jon,

      That’s good to know. It sounds like something that should change in Rails though, right? I do not know enough about Rails to comment but is there a reason why shove operator should not make the model object dirty?

      Thanks for the info!

      tundal45

      November 10, 2010 at 4:34 pm


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: