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.