[email protected] writes:
If you pass an immutable type by reference, does it make a sound?
obj << “hi”
I still wouldn’t call this pass by reference (see my earlier post in
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