开发者

Crazy behavior (at least to me) when setting one string to another in Ruby

As a novice it's probably something about Ruby I missed, but for the life of me I don't understand this result. So I have this simple function:

def crazyfunc(s)
  s.gsub!('a'开发者_如何学运维, 'b')
  #return has not purpose here
end

Now I have this simple few sets.

s1 = 'abc'
s2 = s1
s2 = crazyfunc(str2)

puts s1

=> bbc

Why in the world is s1 affected by crazyfunc? So doing this instead:

def crazyfunc(s)
  return s.gsub('a', 'b')
end

doesn't change str1, so I figure it's got to do with what the inplace gsub is doing. But I still don't get the logic of why str1 would be changed.


String assignment in Ruby doesn't implicitly copy the string. You are simply assigning another reference to it. If you want to copy the string, use clone.

To demonstrate, you can check object IDs:

ree-1.8.7-2010.02 > a = "foo"
 => "foo"
ree-1.8.7-2010.02 > b = a
 => "foo"
ree-1.8.7-2010.02 > a.object_id
 => 81728090
ree-1.8.7-2010.02 > b.object_id
 => 81728090

Since a and b have the same object ID, you know they're the same object. If you want to modify b as a copy of a, you can either use methods which return a new string (like gsub rather than gsub!), or you can use b = a.clone, and then operate on b.

ree-1.8.7-2010.02 > a = "foo"
 => "foo"
ree-1.8.7-2010.02 > b = a.clone
 => "foo"
ree-1.8.7-2010.02 > a.object_id
 => 81703030
ree-1.8.7-2010.02 > b.object_id
 => 81696040
ree-1.8.7-2010.02 > b.gsub! "f", "e"
 => "eoo"
ree-1.8.7-2010.02 > a
 => "foo"
ree-1.8.7-2010.02 > b
 => "eoo"

Or more simply:

ree-1.8.7-2010.02 > a = "foo"
 => "foo"
ree-1.8.7-2010.02 > b = a.gsub("f", "e")
 => "eoo"
ree-1.8.7-2010.02 > puts a, b
foo
eoo


You are running into the fact that everything in Ruby is an object, and that variables are just object references.

When you assign str1 = to str2, you are actually pointing them at the same object. When you then change the object pointed to by str2, you are also changing the object pointed to by str1.

In your original crazyfunc, you modify the string, return the modified string, and then change the value of the object pointed to by str2 - and str1, since they point to the same object.


s1 = 'abc'
s2 = s1
s2 = crazyfunc(str2)

A #master

B = A

C = B

A is A, and B equals A and C equals B. If you change B it doesn't affect A but affects C. See how it cascades down. The variables you list are just pointers.

So you only have 1 master variable here and you need to declare two.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜