From: Rick DeNatale Date: 2007-09-05T02:05:33+09:00 Subject: Re: assigning to hash keys when there is a default value? On 9/3/07, Robert Klemme wrote: > 2007/9/3, dblack@wobblini.net : > > x ||= y is, I think, always supposed to be exactly equivalent to > > x = x || y, ... > I can't point my finger on it but I believe x||=y is equivalent to > "x=y unless x" instead of "x=x||y". It seems to be more reasonable to > skip the assignment altogether if the value is true equivalent > already. That would also explain behavior much better. :-) Robert, Although I can't find the documentation quickly, although I'm 95% certain that it should be in the pickaxe somewhere, I'm pretty sure that you are correct. I've just looked at parse.y and eval.c for ruby1.8.6 and it would appear that: h[2] ||= 10 gets compiled to a NODE_OP_ASGN_OR node with h[2] as the lhs and 10 as the rhs. Here's the code from eval.c which evaluates such a node: case NODE_OP_ASGN_OR: if ((node->nd_aid && !is_defined(self, node->nd_head, 0)) || !RTEST(result = rb_eval(self, node->nd_head))) { node = node->nd_value; goto again; } break; So what happens is that the lhs is only evaluated if the the lhs (node->nd_head) is not defined || it evaluates to an untrue value. In the case of h[5] the default value for the hash means that it will evaluate to 5, and the assignment is not done. I for one, am glad that it works this way. The ruby idiom x ||= y is heavily used for lazy initialization/caching. While most often, it's the rhs which is expensive to compute and therefore the thing we want to short-circuit, since x= can in general be a method, and might just be expensive, then optimizing the case where it boils down to x = x as a nop, makes sense. -- Rick DeNatale My blog on Ruby http://talklikeaduck.denhaven2.com/