Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does `<<` append to a Ruby string while `+=` does not? [duplicate]

I'm working through a tutorial right now, and I'd like to understand why the following occurs:

original_string = "Hello, "
hi = original_string
there = "World"
hi += there
assert_equal "Hello, ", original_string

original_string = "Hello, "
hi = original_string
there = "World"
hi << there
assert_equal "Hello, World", original_string

Why does += have no effect on original_string, and << does? I was absolutely certain that the second case would also equal "Hello, ", but that's not the case.

hi = original string in the first example appears to copy the value of original_string into hi, but hi = original string in the second example appears to set hi to point to the same string as original string. I would guess there is some kind of implicit decision behind the scenes as to whether to copy the value or copy the reference... or something.

like image 935
CptSupermrkt Avatar asked Apr 18 '14 16:04

CptSupermrkt


People also ask

How do you append to a string in Ruby?

In Ruby, we use #concat to append a string to another string or an element to the array. We can also use #prepend to add a string at the beginning of a string.

How do you remove the last character of a string in Ruby?

The chop method is used to remove the last character of a string in Ruby. If the string ends with \r\n , it will remove both the separators. If an empty string calls this method, then an empty string is returned. We can call the chop method on a string twice.

How do I replace in Ruby?

The replace() is an inbuilt method in Ruby which replaces the contents of the set with the contents of the given enumerable object and returns self. Parameters: The function accepts an enumerable object which to be replaced in the set.


2 Answers

<< on string mutates the original object while += creates a copy and returns that.

See the object_id of the respective strings below:

2.1.1 :029 > original_string = "Hello, "
 => "Hello, " 
2.1.1 :030 > hi = original_string
 => "Hello, " 
2.1.1 :031 > there = "World"
 => "World" 
2.1.1 :032 > original_string.object_id
 => 70242326713680 
2.1.1 :033 > hi.object_id
 => 70242326713680 

2.1.1 :034 > hi += there
 => "Hello, World" 
2.1.1 :035 > hi.object_id
 => 70242325614780 

Note the different object_id on hi on line 35. Once you reset hi to original_string in your example above, and use <<, it modifies the same object.

like image 157
CDub Avatar answered Oct 20 '22 17:10

CDub


In both examples, hi = original_string copies the reference.

With +=, however, you reassign hi to point to a new string, even though the variable name is the same.

This is because hi += there expands in the interpreter to the expression hi = hi + there.

Before this operation, hi and original string share a reference to the same string object. Upon the = operation in the expanded expression, hi now references the newly-created string result of hi + there.

In the expression hi << there, nothing happens to change which object hi refers to. It refers to the same string as original_string, and therefore both hi and original_string reflect the change (which is of course due to the fact that they both reference the same string object).

like image 44
user513951 Avatar answered Oct 20 '22 16:10

user513951