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?!
13 Comments on “Ruby shovel operator: What the?!”
You can track this conversation through its atom feed.
I'm Angela, by the way. There are lots of wonderful reasons for these studies; my favorite is because collaboration actually works better than coercion. If you'd like to know more about Agile, I'd encourage you to read
This guy is an
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?
Posted on January 6, 2011 at 11:00 am.
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”?) :)
Posted on January 6, 2011 at 11:09 am.
Tweets that mention Ruby shovel operator: What the?! at My Agile Education -- Topsy.com says:
[...] This post was mentioned on Twitter by Jose Manuel Beas. Jose Manuel Beas said: RT @angelaharms: A Ruby question: Ruby shovel operator: what the? http://bit.ly/RubyShovel [...]
Posted on January 6, 2011 at 11:35 am.
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
Posted on January 6, 2011 at 12:15 pm.
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.
Posted on January 12, 2011 at 9:55 am.
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.
Posted on January 20, 2011 at 3:56 pm.
“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.
Posted on February 17, 2011 at 9:33 pm.
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, “
Posted on February 25, 2011 at 12:38 am.
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.
Posted on March 21, 2011 at 9:24 pm.
Has anyone noticed that hi += there does NOT modify original_string,
but hi << there DOES?
That is at least interesting if not downright weird.
Posted on November 19, 2011 at 9:17 pm.
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.
Posted on May 14, 2012 at 12:03 am.
Season of Ruby – Learning the Syntax « Old Dog, New Tricks says:
[...] moment with the shovel operator ” <<” versus “+=”, but I am not alone there. After Googling around it made sense and this article about the performance differences was a [...]
Posted on January 21, 2012 at 12:36 pm.
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.
Posted on March 12, 2012 at 2:37 pm.