I ran into this weird side effect that caused a bug or confusion. So imagine that this isn't a trivial example but an example of a gotcha perhaps.
name = "Zorg"
def say_hello(name)
greeting = "Hi there, " << name << "?"
puts greeting
end
say_hello(name)
puts name
# Hi there, Zorg?
# Zorg
This doesn't mutate name. Name is still Zorg
.
But now look at a very subtle difference. in this next example:
name = "Zorg"
def say_hello(name)
greeting = name << "?"
puts "Hi there, #{greeting}"
end
say_hello(name)
puts name
# Hi there, Zorg?
# Zorg? <-- name has mutated
Now name is Zorg?
. Crazy. Very subtle difference in the greeting =
assignment. Ruby is doing something internally with the parsing (?) or message passing chaining? I thought this would just chain the shovels like name.<<("?")
along but I guess this isn't happening.
This is why I avoid the shovel operator when trying to do concatenation. I generally try to avoid mutating state when I can but Ruby (currently) isn't optimized for this (yet). Maybe Ruby 3 will change things. Sorry for scope-creep / side discussion about the future of Ruby.
I think this is particularly weird since the example with less side effects (first one) has two shovel operators where the example with more side effects has fewer shovel operators.
Update You are correct DigitalRoss, I'm making it too complicated. Reduced example:
one = "1"
two = "2"
three = "3"
message = one << two << three
Now what do you think everything is set to? (no peeking!) If I had to guess I'd say:
one is 123
two is 23
three is 3
message is 123
But I'd be wrong about two. Two is 2.