From: Josh Cheek Date: 2010-10-03T13:40:55+09:00 Subject: Re: Pass by reference and copy on write --001485f1e44064ddbc0491af08a6 Content-Type: text/plain; charset=ISO-8859-1 On Sat, Oct 2, 2010 at 10:57 PM, Caleb Clausen wrote: > > It's just that in the case of Fixnums (and a few other things) it is > >> not possible to have references at all; such objects are always stored > >> (and passed) by value > > > > If it were pass by value, I would expect it to make a new object each > time > > it passes that object. > > It does make a new object when you pass a Fixnum as a parameter; the > Fixnum is copied into a different cell in memory. Fixnums are > compressed so that the Fixnum value is stored within the reference to > it. So I guess Fixnums are kinda value and reference all wrapped up in > one burrito. > > Convinced? I'm not sure I am. > > How about in this case? def add_ivar(remote) remote.instance_eval do @ivar = "added in function" end nil end local = 1 add_ivar(local) local.instance_variables # => [:@ivar] Here, if I understand you, you are saying that add_ivar's object "remote" and main's object "local" are not the same object, because it creates a new object when we pass local as a parameter. However, in add_ivar, we open up remote and add an instance variable to it. At this point, that ivar should exist on the add_ivar's "remote" and not on main's "local". When we return, we pass back nil, just to ensure that add_ivar's "remote" is never an arg, and should simply be discarded when scope leaves the add_ivar method. However, back in main, we can see that the ivar that it added does in fact exist on main's "local". How did it get there, since it is a different object than the one we mutated? > def mutate_myvar(remote) > > remote.instance_eval { @myvar = "bye" } > > end > > def oid(remote) > > remote.send :object_id > > end > > local = 1 > > local.class # => Fixnum > > local.instance_eval { @myvar = "hi" } > > local.instance_eval { @myvar } # => "hi" > > mutate_myvar(local) > > local.instance_eval { @myvar } # => "bye" > > local.send(:object_id) == oid(local) # => true > > You have just demonstrated that Fixnums are not immutable after all, > since their instance variables can be changed. I had forgotten that. > Deliberately. > > You do realize, don't you, that instance variables on Fixnums (and > Symbols, and nil/false/true) is an evil hack, to be avoided by all > sane and reasonable code? All instances of the Fixnum 1 share the same > set of instance vars... ulh. > Yes, this code is merely intended to illustrate why I think they are pointing to the same object. --001485f1e44064ddbc0491af08a6--