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