Ruby shovel operator: What the?!

This is taken from the Ruby Koans. It’s the shovel operator, and it appends stuff to a string.


    original_string = "Hello, "
    hi = original_string
    there = "World"
    hi << there

So I'm totally down with the idea that hi now equals "Hello, World". No problem. But in fact, original_string also now equals "Hello, World". That is totally messed up! :)

But seriously. What is up with that? is there way to not find this just... just... shocking?!

15 thoughts on “Ruby shovel operator: What the?!

  1. Todd Kaufman

    In line 2 you create a pointer to the original original string, not a new object. So both hi and original_string point to the same thing. Any changes made via hi or original_string will affect the same underlying object.

    Make sense?

    Reply
  2. Angela Post author

    It does, and I figured that was the case, but I still find it astounding. Wonder how that’s going to become intuitive, but I suppose everything does, eventually, right? :)

    But isn’t it dangerous? Seems like a really likely place to get into serious trouble. Knee deep in code, how would I know if something is a legit variable or a pointer to something else?

    Is there some other way besides alpha = beta to assign a value without just creating a pointer?

    (Is this where you say “Relax, grasshopper. All will become clear in time”?) :)

    Reply
  3. Pingback: Tweets that mention Ruby shovel operator: What the?! at My Agile Education -- Topsy.com

  4. Todd Kaufman

    Prolly should relax, but the important thing is that all variables are just pointers to something. You can get a new object based on a current one via clone or dup. See irb fun below:

    >> a = "Angela"
    => "Angela"
    >> b = a
    => "Angela"
    >> b < "Angela is learning ruby!"
    >> puts a, b
    Angela is learning ruby!
    Angela is learning ruby!
    => nil

    versus

    >> a = "Angela"
    => "Angela"
    >> b = a.dup
    => "Angela"
    >> b < "Angela is learning ruby!"
    >> puts a, b
    Angela
    Angela is learning ruby!
    => nil

    Reply
    1. Vagner

      += does the same:

      >> a = “Angela”
      => “Angela”
      >> b = a
      => “Angela”
      >> b += ” is learning ruby!”
      >> puts a, b
      Angela
      Angela is learning ruby!
      => nil

      Reply
      1. Vagner

        That’s not all the truth.
        There are 3 types of strings at ruby runtime:
        - Heap strings (that has pointers to malloc’ed heap memory).
        - Shared strings (str1 = str2; str1.object_id == str2.object_id;). It also has pointers to malloc’ed heap memory.
        - Embedded strings (those stores the string data inside a char array within itself).
        When you use the shovel operator with a Shared string, it follows the pointer to the string data stored in heap and changes it. But when you use the += operator, it kills the Shared string and creates a new one, Heap or Embedded depending on the length of it.

        Reply
  5. Sean McMillan

    This appears to be the same semantics as python, where I learned this alternate formation:

    Stop thinking of = as an assignment.

    The = operator performs a binding operation, tying a name (on the left,) to an object (on the right.) Values are never changed, only bindings are changed.

    Thinking of it in terms of name binding instead of assignment makes it more intuitive for me.

    Reply
  6. Shih-gian Lee

    Ruby String object is different than the String in language like Java. One thing to notice is Ruby String is mutable.

    In Java, if we have:

    String a=”Hello”;
    String b=a;
    String c=b + ” World”;

    We will have the following output:
    Hello //b
    Hello World //c

    The “+” operator returns a new instance of String because String is immutable.

    In Ruby, since String is mutable, any variable that is pointing to the same String will be effected. This design is consistent with other objects in Ruby. If you want a Ruby object to be immutable, we can use String#frozen to prevent it from being changed.

    Reply
  7. rdm

    “Is there some other way besides alpha = beta to assign a value without just creating a pointer?”

    I think when you pass arguments to methods, and those arguments are references to objects, the method gets those references to objects.

    In other words:

    hammer.pound(nail)

    can bend the nail (if nails are things that can be bent).

    This is almost the essence of object oriented programming, I think.

    Reply
  8. xtoddx

    You’re looking for the ‘dup’ method.

    irb(main):001:0> original_string = “Hello, ”
    => “Hello, ”
    irb(main):002:0> hi = original_string.dup()
    => “Hello, ”
    irb(main):003:0> there = “World”
    => “World”
    irb(main):004:0> hi < “Hello, World”
    irb(main):005:0> hi
    => “Hello, World”
    irb(main):006:0> original_string
    => “Hello, “

    Reply
  9. Jon Kern

    If you step back and don’t think so hard (or with the biases of other languages), why would you expect any different outcome?

    original_string = “Hello, ”
    hi = original_string
    there = “World”
    hi << there

    You are appending ‘there’ to ‘hi’ and it stands to reason that you end up with the two strings as “Hello, World”

    Maybe you were expecting Ruby to be more difficult?

    What I have learned — and attempt to imitate — is that Ruby code should be obvious and comfortable.

    Reply
    1. James

      When you type

      hi += there

      you are making hi point to the string that you get when you concatenate “Hello, ” and “World”. You have created a new object and now hi is pointing to it. If you type

      hi << there

      you are slapping "World" onto the end of the string that hi points to. original_string points to the same string object.

      The big difference between the two operators is this:

      += creates a new string object.

      << adds characters to an existing object.

      Reply
  10. Pingback: Season of Ruby – Learning the Syntax « Old Dog, New Tricks

  11. Adan Byerly

    And we don’t have a very monopoly. We have business. There’s a difference.
    Don’t get worried about people stealing your thinking. If your ideas are any good, you need to ram them down people’s throats.

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>