dblack / wobblini.net writes:

> Hi --
>
> On Sat, 27 Jan 2007, Robert Klemme wrote:
>
>> On 27.01.2007 01:43, dblack / wobblini.net wrote:
>>> Hi --
>>> 
>>> On Sat, 27 Jan 2007, Martin C. Martin wrote:
>>> 
>>>> Phrogz wrote:
>>>>> If you pass an immutable type by reference, does it make a sound?
>>>>> Er, I mean...
>>>>> If you passed an immutable type by reference, how would you know that
>>>>> it wasn't passed by value?
>>>> 
>>>> Is there any way for the function you're calling to modify the value of 
>>>> the variable in the caller?  Pass by reference can do that.
>>> 
>>> You can modify the object to which the variable refers:
>>>
>>>   def change_me(obj)
>>>     obj << "hi"
>>>   end
>>>
>>>   arr = [1,2,3]
>>>   change_me(arr)
>>>   p arr          # [1, 2, 3, "hi"]
>>> 
>>> In this example, arr contains a reference to an array.  In change_me,
>>> obj contains another copy of the same reference, so you can use it to
>>> manipulate and change the original array.
>>> 
>>> I still wouldn't call this pass by reference (see my earlier post in
>>> this thread).
>>
>> Absolutely right: Ruby uses pass by value - with references.
>>
>> irb(main):004:0> def foo(x) x = 10 end
>> => nil
>> irb(main):005:0> def bar; x = 20; foo(x); x end
>> => nil
>> irb(main):006:0> bar
>> => 20
>> irb(main):007:0>
>
> I'm not sure that demonstrates the "values that are references" thing,
> though.  You're reassigning to x in foo, which creates a new local x;
> but I think that's just part of the assignment semantics.  Or are you
> assuming that if pass by reference were involved, then assignment
> would work differently?
>

*** NEWBIE WARNING ***

I'm entering this thread as it gives me a chance to test my own understanding.
My apologies if I've missed the mark!

I agree the example doesn't show pass by reference v pass by value. I think it
shows more about scope. 

However, I think what he was trying to show was that if what was being passed
was the address of the variable in the callers environment, then changes to
what that variable pointed at would be seen in the callers environment as well. 

i.e. 

a = Array.new could look like this

-------
|  a  |        ----------
|  ----------->|Array Obj|
|     |        ----------
-------        Addr = 1000
Addr = 0

Here 'a' holds the value 1000, the address of the array object. This value
(1000) is stored in location 0. 'a' points to the storage location. In C it
would be called a pointer, in ruby, its just a variable because yo don't have
anything else. some would say 'a' is bound to the address 1000, which is the
start location of an array object. 

Some of this confusion about passed by value and passed by reference is due to
C and how it worked. In C, by default, things are passed by value, but you can
only pass 'simple/base' types. Passing by value has the disadvantage that it can
have considerable overhead as the data being passed has to be copied and you
cannot modify the data such that the modifications exist after the procedure
terminates - modifications are local to the procedure because you are operating
on a local copy. 

However, what people often miss is that, depending on the implementation, most
of the time, even passing a reference involves a copy. However, as what you are
copying is the address of the storage location where the data is located, the
copy operation is independent of the size of the data being referenced - its
simply a copy of an address and all addresses are essentially the same size. As
you are copying the address of the storage location, you can reference that
location from within the procedure and any modifications you make would affect
that data in the callers environment as well. 

Ruby takes a different approach to C. In ruby, all variables are really
references to objects stored somewhwere else. The overheads associated with
arguement passing are the same regardless of the size or type of object the
variable references - its just an address. This means the traditional C pass by
reference and pass by value doesn't really apply in Ruby (or languages like
Java). All that nasty C referencing and dereferencing is handled under the hood
and the only ones upset are those clever geeks who use to do all sorts of
amazing pointer arithmetic that would take us mere mortals hours to grok. 

Now, back to Ruby and the issue of whether the arguments to a procedure are
truely pass by reference or pass by value. Essentially, I don't think the
concept really makes sense from the Ruby perspective. However, I guess it could
be argued that if ruby was pass by reference with respect to arguments, this
would mean it passes the reference (address) of the variable. In the above
example, this would be the address of a, which is 0. If it was pass by value,
it would pass a copy of its contents, which is 1000. 

If arguements were pass by reference, changes to what the address pointed to
would be seen in the callers environment i.e. address 0 would point somewhere
else. If it is pass by value, changes to what the argument variable points to
will be lost once the procedure exits and returns to the calling environment
because the argument is a copy. so

a = Array.new ------> Address 0 holds the value 1000, the address of the array.
def foo(b)
  b = Array.new -------> b points to array object at address 2000 (new array obj) 
end

 If ruby was pass by reference, the address of a and b wold be the same i.e. 0.
 If it is pass by value, it would be different. 

If a and b have the same address (i.e. 0) then after foo(a), a will boint at
the second array object (ie. contain address 2000). 

Again, in languages like Ruby and Java, the by reference v by value really
doesn't make much sense because variables all hold references to the data
rather than holding the data directly. Generally, as conceptually (with respect
to argument passing), it is convenient to think of Ruby arguments as pass by
reference, but if you want to be really technically accurate, its pass by
value. 

So, how successfully has that been at muddying the water? Everyone now nicely
confused?

Tim

-- 
tcross (at) rapttech dot com dot au