Keir Finlow-Bates
Keir Finlow-Bates

Reputation: 1053

Why do Ruby strings change by value with one operation and by reference with another

The following code:

 test_1 = "my test string"
 test_2 = test_1
 test_2[3] = "B"
 puts test_1
 puts test_2

 test_1 = "my test string"
 test_2 = test_1
 test_2 = test_2 + ""
 test_2[3] = "B"
 puts test_1
 puts test_2

produces the following result:

 my Best string
 my Best string
 my test string
 my Best string

Can some explain to me why in the first case both strings are altered (as though test_2 is being assigned by reference) but in the second case only test_2 changes (as though by value)?

Upvotes: 0

Views: 75

Answers (2)

Arup Rakshit
Arup Rakshit

Reputation: 118261

Here is the clarification :

test_1 = "my test string"
test_2 = test_1

test_2.object_id # => 83607730
test_1.object_id # => 83607730

test_2 = test_2 + ""

test_2.object_id # => 83606390
test_1.object_id # => 83607730

String#+ created a new object. Thus test_2[3] = "B" added "B" to the new object referenced by test_2.It wouldn't change the object,whose reference is horded by test_1. Which is not the case in below :

test_1 = "my test string"
test_2 = test_1

test_2.object_id # => 70466640
test_1.object_id # => 70466640

Here test_2 and test_1 both holds the reference to the same object. Thus when you are doing test_2[3] = "B",it is basically doing change in the same object which is referenced by the local variables test_1 and test_2.

Upvotes: 3

kristinalim
kristinalim

Reputation: 3459

When you declare "test" in Ruby, this creates a new String object.

"test".object_id   # => 9157960
"test".class       # => String

And when you assign a string to a variable, you point the variable to the string object on the other side of the assignment.

Take a look at the following:

# Point variable to first String object.
a = "test"         # => "test"
a.object_id        # => 9307800

# Point variable to second String object.
b = "test"         # => "test"
b.object_id        # => 9307760
a.equal?(b)        # => false

# Point variable to first String object.
c = a              # => "test"
c.object_id        # => 9307800
a.equal?(c)        # => true

So when you manipulate a here, you manipulate the object where c points.

Upvotes: 3

Related Questions