On 10/2/10, Josh Cheek <josh.cheek / gmail.com> wrote:
> On Sat, Oct 2, 2010 at 10:57 PM, Caleb Clausen <vikkous / gmail.com> 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?

I would say that passing a fixnum does indeed make a new 'copy' of it,
for that method call. BUT, since, as you say below, fixnums are
singletons, and there's only ever one 'instance' of any given fixnum.
Changes to the fixnum's state affect the value seen by the caller as
well.

There doesn't need to be a method call to see the paradox of fixnum
state sharing in effect. Watch:

var1=1
var2=1 #a fresh, new copy of the fixnum 1
var1.instance_eval{@x=:foo}
p var2.instance_eval{@x}  #=>:foo #whoa!, var1 and var2 share state!

But this same behavior is not seen with other numeric classes, like
Float and Bignum.

Frankly, I think  that it should not be possible to set instance
variables on the built-in immutable classes: Fixnum, Bignum,
true/false/nil, Float, Symbol.


I like Rick's terminology: pass by object reference. I think that
makes it a little clearer what is really going on. Then if you
understand the subtleties of how Fixnums are actually packed into
their object references, you'll understand what is going on, and why
they behave differently than other classes.