From: Rob Biedenharn Date: 2009-07-24T01:12:48+09:00 Subject: Re: How to get real reference to an object? On Jul 23, 2009, at 10:25 AM, Pavel Smerk wrote: > David A. Black wrote: >> On Thu, 23 Jul 2009, Pavel Smerk wrote: >>> Assume a big hash and/or a nested structure and the need of a >>> plenty of operations on some hash[...][...][...] which is Float. >>> How can one avoid the repetitious evaluation of the indices? I >>> have not been able to get a "real" reference to that variable to >>> do _something_like_ tmp = referenceof(hash[...][...][...]) and >>> work with the value directly through the (dereferenced) tmp >>> variable. In Perl I would say >>> >>> $ perl -e '$x[1][2][3] = 1; $a = \$x[1][2][3]; $$a = 3; print $x[1] >>> [2][3]' >>> 3 >>> >>> (where \... is a reference and $ before $a is a dereference). >> h = { :a => { :b => {} } } >> tmp = h[:a][:b] >> tmp[:x] = "hi" >> tmp[:x] << " there" >> p h # => {:a=>{:b=>{:x=>"hi there"}}} > > Yes, but I need something like: > > $ ruby -e 'h = { :a => { :b => "hi" } }; tmp = h[:a][:b]; tmp << " > there"; p h' > {:a=>{:b=>"hi there"}} > > which is OK, but not for Float: > > $ ruby -e 'h = { :a => { :b => 5.0 } }; tmp = h[:a][:b]; tmp += 5.0; > p h' > {:a=>{:b=>5.0}} > > And that's why I'm asking for a "real" reference, because tmp > apparently is not any kind of reference to the h[:a][:b]. > Well, it is, but Fixnum's are immediate (implementation detail) and Float's act like value objects. What would happen if: 5.0 += 5.0 were legal? All 5's now act like 10's?? >> You're (almost) always dealing in references in Ruby. (And the almost >> part doesn't affect you much anyway.) Every reference is exactly one >> step away from the object; there's no such thing as a reference to a >> reference. It's very different from Perl in that respect. > > Mhm, an unfortunate difference, I'm afraid... > > Of course, I could write tmp = h[:a] and then many times tmp[:b]. > But something like simple tmp as in Perl would seem to me far more > elegant. > >>> Morover, why the return value of the assignment is not an l-value? >>> The following is legal in Perl ($x ||= 1) *= 2 --- why it is not >>> legal in Ruby as well? >> I assume it's because (x ||= 1) evaluates to the object 1, and 1 *= 2 >> doesn't make sense. > > I know, my question is, why it does not evaluate to x. Then it would > have the same value (the value of x) and moreover it could stand on > the left side of an another assignment (as the x *= 2 does make > sense). > > Thanks, P. Because in Ruby, "x.y = z" is just syntactic sugar when x is an object for: x.send(:y=, z) with the rule that the "value" of an assignment is the right-hand side (i.e., z) so things like w = x.y = z are predictable (meaning that the "y=" method sent to x can't return something other than z for the assignment to w. (And, the rule breaks down if you don't use the sugar, but make the calls yourself: w = x.send(:y=, z) might result in w != z, but any programmer that does such a thing in "real" code should be punished.) -Rob Rob Biedenharn http://agileconsultingllc.com Rob@AgileConsultingLLC.com