From: Austin Ziegler Date: 2005-01-20T01:39:29+09:00 Subject: Re: value by reference On Wed, 19 Jan 2005 23:03:59 +0900, Glenn Parker wrote: > Florian Gross wrote: >> See my earlier posting about the lambda { } and Variable[:name] >> ways of doing this. > Sorry, but I can't believe anybody would actually want to use the > lambda styles as proposed. They are ugly and obscure. The Variable method is useful; I agree about lambda for this bit. >> Ruby itself just treats variables as names for Objects. You can't >> really refer to a variable itself, you can only refer to the >> Object it is a name for. That's a surprisingly simple and >> non-confusing model. > Judging by the frequency that this issue is discussed, it's more > confusing than you suggest. I disagree. The problem is when it's explained that everything is a reference. The best description I've seen for this was said a month ago or so: Ruby's calling semantics are pass by value, but the value passed is a reference to an object. People *understand* pass by value and people *understand* pass by reference, but only after it's been explained to them. This is no different; you have to learn the calling semantics. It's pass-reference-by-value. Don't think too much about variables -- they're just names, not memory blocks. > A typical programmers expects call-by-reference to work one way, > and Ruby works differently. Extra confusion results because this > difference is masked by using self-updating methods, but it always > fails for immediate objects, and it eventually fails in a > surprising way for non-immediate objects. I call it surprising > because a typical programmer does not expect the assignment > operator to destroy call-by-reference, but that is exactly what > happens. This has been a situation where people are applying the concepts of C/C++ and similar languages (where variables are slots in memory) to Ruby (where variables are simply labels for object references). Variables are programmers' tools in Ruby; nothing more, nothing less. > def inc1(a, i); a += i; end > def inc2(a, i); a = a + i; end > To the naive Ruby programmer, inc1 and inc2 seem to be equivalent, > but Ruby gurus just shake their heads and sigh while they explain, > yet again, that there is a difference. Why is this considered a > good thing? :) Um. They *are* the same thing. "a += i" is syntax magic for "a = a + i". Perhaps you're referring to something like: def app1(a, i); a << i; end def app2(a, i); a += i; end And these are *not* the same, and never should be considered the same. The problem again is that people are coming at it from the wrong perspective. > You might say that the typical programmer has grown accustomed to > a confusing model, and Ruby is better off without that model. But, > that is nigh on saying that Ruby is better off without the typical > programmer. And that would be a shame, since Ruby has much to > offer the hordes of Perl and Python programmers looking for > something better. Except that Ruby's call model isn't that far from the way that Perl works. Probably not far from Python's model, either. > Ruby does *not* support call-by-reference, in the traditional > sense of the term. Instead, it is strictly call-by-value, and > formal paremeters are copies of references from the calling scope. > If Ruby had real call-by-reference, then it would be trivial to > define a procedure that updates a variable from its parent's > scope, and inc1 and inc2 above would be equivalent. Again, inc1 and inc2 are equivalent. However, Ruby doesn't have or need "real" call-by-reference. Too many risks of bad programming options, IMO. >> I think Ruby itself should not be changed. (Though it would be >> nice if it had something like Binding.of_caller built-in...) > Tcl is similar to Ruby, regarding both the style of variable > passing and the resulting confusion among its new adopters, but > Tcl documentation has always stressed the details of this issue, > and the Tcl core has the "uplevel" and "upvar" builtins. I'm not a > huge fan of Tcl, but I do think the Tcl folks handled this issue > in the best way possible. Right. Now that we've got a way of expressing this clearly (Ruby's calling semantics are pass-reference-by-value), this should no longer be a source of confusion as documentation is updated. -austin -- Austin Ziegler * halostatue@gmail.com * Alternate: austin@halostatue.ca