From: Brian Candler Date: 2012-05-17T21:45:59+09:00 Subject: Re: Passing by reference - modifying instance variables John Cooper wrote in post #1060987: > The instance variable title of song2 has been modified. This makes sense > to me, since the variables are passed by reference Just to be clear: in ruby there is *no* pass by reference. Never. It is all pass-by-value, but the value is an object reference. This is important, because it is impossible to pass a reference to a local variable (as you can in some other languages) and have the local variable updated remotely. Local variables are not objects, and you cannot refer to them as if they were. So when you do title.downcase! you are *not* changing the value of title (which still refers to the same object); you are mutating the object it refers to. Simple example: a = "foo" b = a puts b.object_id b.upcase! puts b.object_id puts a # FOO puts b # FOO a and b contain the same value, which is the same string object "FOO". b.upcase! does not change the variable b, but it changes the string object. > I guess I'd need to > return a copy from my accessor method to avoid this happening. Is there > a neat way to do this? def title @title.dup end But this is not a common Ruby idiom, because it does not work in the general case, for example where dup is an array, or any more complex graph of objects. Such a "deep copy" is possible, but increasingly inefficient the more objects are included in the graph. A slightly more common idiom is to freeze the object, if you don't want the caller messing with it. But normally you would trust the caller to behave. > To add further confusion, the code in the attachment reference2.rb - > with an identical definition of the class Song, with a call to > .downcase! in WordIndex::index does not modify the instance variables in > the Song class phrase.scan(/whatever/) returns an array of new String objects with each of the matches. >> a = "foo" => "foo" >> b = a.scan(/.../) => ["foo"] >> a.object_id => 2201532960 >> b.first.object_id => 2201525680 So a and b.first are two distinct Strings, although they both contain the characters "foo" -- Posted via http://www.ruby-forum.com/.