Why is foo <<= "bar" syntactically valid Ruby

I saw the following question on Twitter:

Bonus points to anyone that can explain why this works in ruby: stringvar <<= "appendthis". Just saw it working and <<= is not an operator.

That it was indeed valid syntax puzzled me a bit, but then I realised it was just a form of abbreviated assignment, albeit one I've never actually seen used.

A more common form of abbreviated assignment is +=, which works like the following:

s = ""
s += "foo"    # => "foo"
s             # => "foo"

# equivalent to

s = ""
s = s + "foo" # => "foo"
s             # => "foo"

<< is also an operator that works with abbreviated assignment, working like the following:

s = ""
s <<= "foo"    # => foo
s              # => foo

# equivalent to
s = ""
s = s << "foo" # => foo
s              # => foo

Now the reason you might see += in normal ruby code, but not <<=, is that while + for String returns a new object, << modifies the existing object.

s = ""
s + "foo"  # => "foo"
s          # => ""

s = ""
s << "foo" # => "foo"
s          # => "foo"

Because of this, in the case of String, s <<= "foo" and s << "foo" are basically equivalent. Given this, why is <<= an allowed form of self assignment in the first place? Because sometimes << doesn't modify self. For instance, Fixnum#<< performs a bitwise left shift.

Now we could see a difference in the behaviour of << and <<=.

i = 1
i << 1  # => 2
i       # => 1

i = 1
i <<= 1 # => 2
i       # => 2

So while there might not be a reason to use <<= with Strings, it might be useful with other types of objects.


About Paul

Co-founder of Doorkeeper. Based in Tokyo. Read more about being a Japan based entrepreneur and developer at Tokyo Dev. You can also follow him on Twitter.

Become a better developer

Get tips on becoming a better and faster developer, straight to your inbox.