Reputation: 3081
I came across a snippet of code in Ruby that confused me. Boiling it down to a simple example below to illustrate. Why is it that sArr does not have its contents automatically updated in the first case but it happens in the second case? The snippets are short and self explanatory with three returns separating the two scenarios.
2.0.0-p598 :068 > str = "Hello"
=> "Hello"
2.0.0-p598 :069 > sArr = [str]
=> ["Hello"]
2.0.0-p598 :070 > str = str.upcase
=> "HELLO"
2.0.0-p598 :071 > str
=> "HELLO"
2.0.0-p598 :072 > sArr
=> ["Hello"] # Why is this not ["HELLO"] like in the sequence below?
2.0.0-p598 :073 >
2.0.0-p598 :074 >
2.0.0-p598 :075 >
2.0.0-p598 :076 > str = "Hello"
=> "Hello"
2.0.0-p598 :077 > sArr = [str]
=> ["Hello"]
2.0.0-p598 :078 > str.upcase!
=> "HELLO"
2.0.0-p598 :079 > sArr
=> ["HELLO"]
Upvotes: 1
Views: 69
Reputation: 20796
This is because a new String instance is created with str = str.upcase
but not str.upcase!
:
str = "Hello"
str.object_id
# => 70132476337960
str = str.upcase
# => "HELLO"
str.object_id
# => 70132476374360 (new instance)
str = "Hello"
str.object_id
# => 70132476415240
str.upcase!
# => "HELLO"
str.object_id
# => 70132476415240 (same instance)
sArr
is unaffected by str = str.upcase
since it is holding a reference to the initial "Hello"
. Assigning to str
doesn't change the object in sArr
any more than if you did str = 'World'
. In contrast, str.upcase!
modifies the instance held by sArr
.
Upvotes: 5