From: Rick DeNatale Date: 2008-05-03T03:05:31+09:00 Subject: Re: Please explain nuances of ||= On Fri, May 2, 2008 at 12:12 PM, Pit Capitain wrote: > 2008/5/2 Rick DeNatale : > > > 3) I say first approximations because of David Black's observation > > that x ||= y and x || x = y differ when x is undefined. > > They obviously also differ if evaluating x has side effects as in > > h = {} > h[print("f")] ||= 1 > > h = {} > h[print("o")] || h[print("o")] = 1 > > # => foo > > so x ||= y is more like > > ref = &x; *ref || *ref = y > > with the reference (&) and dereference (*) operators of C. But x is different whether its on the RHS or LHS The problem is that it's not a textual substitution. h[1+2] ||= 3 is like arg_temp = 1 + 2 h[arg_temp] || h[arg_temp] = 3 Keep in mind that unlike operators like + and -, || and && are really control flow 'operators' implemented by testing and branching. The same is true of ||= and &&=, which I suppose is the point. Ruby 1.9 makes it somewhat easier to see what's really happening. k$ ruby1.9 -ve'puts VM::InstructionSequence.compile("h={};h[\"a\" + \"b\"] ||= 3").disasm' ruby 1.9.0 (2008-03-21 revision 0) [i686-darwin9.2.2] == disasm: @>================================= local table (size: 2, argc: 0 [opts: 0, rest: -1, post: 0, block: -1] s1) [ 2] h 0000 newhash 0 ( 1) 0002 setlocal h 0004 getlocal h 0006 putstring "a" 0008 putstring "b" 0010 opt_plus 0011 dupn 2 0013 opt_aref 0014 dup 0015 branchif 28 0017 pop 0018 putobject 3 0020 send :[]=, 2, nil, 0, 0026 leave 0027 pop 0028 swap 0029 pop 0030 swap 0031 pop 0032 leave I'm sure that Ruby 1.8 does pretty much the same thing, but I don't have the time to dig through parse.y and eval.c to prove it. -- Rick DeNatale My blog on Ruby http://talklikeaduck.denhaven2.com/