On 7/12/2005, at 8:24 AM, Kent S. wrote:
There’s a strong confusion of what exactly pass-by-reference means.
I always
thought that if a language supports pass-by-reference semantics,
then when
you define a method, one or several parameters can be declared as OUT
parameters.
That’s a completely different thing all together, and not needed in
Ruby, I’ll explain below.
The difference is simple if you understand pointers and C function
calls. Pass by value means that the actual value - the number - gets
copied in to a new memory space for the function, in pseudocode:
int i = 1; // Memory address ‘i’ contains the value 1
int r = add_one(i); // Go to function add_one, value 1 is sent,
memory address r is then set to 2
int add_one(int q) { // Memory address ‘q’ now contains 1
return q+1; // After this memory address ‘return’ for want of a
better description contains 2
}
So i and r are completely separate, change either one and the other
won’t be affected.
This is pass by reference, again in c-ish pseudocode. The memory
address is passed around so the value itself never gets copied.
int* i = 1; // Memory space ‘i’ contains the address of a memory
address that contains 1;
add_one(i); // Go to function add_one, the value passed is the memory
address.
void add_one(int* q) { // Memory address q contains the memory
address from i, this is copied.
*q = *q + 1; // The memory address referenced by q is now set to 2.
This memory address is also referenced by i, so *i is now 2.
}
In this case only one value is used - *i - but references to it are
passed around. All OO languages work like this, but not all objects
can be modified. Here’s another pseudocode example, in Ruby-ish.
i = 1 # i is a reference to an object that behaves like the integer
‘1’. Wordy huh?
add_one(i) # Passes the reference to i in to add_one
def add_one® # r is a reference to the same object referenced by i
r = r + 1 # Integers are immutable, so r is now a pointer to a NEW
object representing ‘2’. r has changed
end
If i was to change when r does then i would have to be a reference to
a reference, and that reminds me of the OS 9 memory manager… Also,
if Ruby was pass-by-value then r would contain a brand new object,
and that reminds me of PHP4, not good.
Pass by reference to return values is only useful for languages
without a native array type and parallel assignment. If you think
it’ll boost speed then you’re thinking on the wrong tracks, you
should look to other areas first, and do a quick search for
‘premature optimisation’.
Here’s a Ruby example of something that has to return two results.
Anything could be returned, they’re all just objects.
def crazy_add(q, r, s)
[q+s, r+s]
end
i, j, k = 2, 3, 4 # i = 2, j = 3, k = 4. Remember the construct.
a, b = crazy_add(i, j, k) # a = 6, b = 7
The key point people seem to be missing is that integers in Ruby are
immutable objects - they can never be changed, but if strings or some
other object was used then modifying in place is easily possible. I
know there are some differences between a normal object and an
Integer for speed reasons, but just think of them as any other
object. In Python strings are also immutable, so a similar issue
could be found.
I hope this does something to clarify the issue.
–
Phillip H.
[email protected]