Ruby Shovel

Published: Sat 05 August 2017

In Blog.

Strings in Ruby are a little different from those in the Python or .NET world. Whilst the latter are immutable, the former aren't. I remember in the days in-which the .NET Dynamic Language Runtime was receiving a lot of attention, the issue of how IronRuby strings would be reconciled with .NET strings was a topic of much debate, since, of course, the CLR has in-built immutable strings whereas Ruby assumes strings are mutable.

In .NET:

csharp> var s = "42";
csharp> object.ReferenceEquals(s, s += "52")

In Ruby:

irb(main):001:0> s = "42"
=> "42"
irb(main):002:0> s.object_id
=> 18181320
irb(main):003:0> s += "52"
=> "4252"
irb(main):004:0> s.object_id
=> 18135580

Wait a second ... shouldn't the object_id’s above be the same? This is where it gets interesting ... yes, strings are mutable, but the "plus equals" operator here, when expanded basically means:

Let s equal a new string object whose value is the old s plus "52"

If we want to actually change the existing s as opposed to creating an entirely new one, we need to use the shovel operator in order to effect a change:

irb(main):005:0> s = "42"
=> "42"
irb(main):006:0> s.object_id
=> 18083880
irb(main):007:0> s << "52"
=> "4252"
irb(main):008:0> s.object_id
=> 18083880

In other articles on the topic, this situation is often presented using two strings, e.g.,

irb(main):012:0> orig = "42"
=> "42"
irb(main):013:0> copy = orig
=> "42"
irb(main):014:0> orig.object_id == copy.object_id
=> true
irb(main):015:0> copy << "52"
=> "4252"
irb(main):016:0> orig
=> "4252"

This is to illustrate the fact that when assigning one variable to another, the reference is assigned (as we would expect, since this is the case for Python and .NET as well). That said, the shovel operator modifies the contents of the referenced variable, which in Java, .NET and Python, is not possible.

Comments !