问题描述:

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.

相关阅读:
Top