On Mon, 3 Sep 2007, 7stud -- wrote: > Can someone explain why there is a difference in the second line of > output for the two hashes:
> h = Hash.new(5)
> puts h[2]
> h[2] ||= 10 > p h
> #---------- > puts > #----------
> h = Hash.new
> puts h[2]
> h[2] ||= 10 > p h
> ---output:-- > 5 > {}
> nil > {2=>10}
x ||= y is, I think, always supposed to be exactly equivalent to x = x || y, so that line in your first hash should be equivalent to:
h[2] = 5 || 10
which should assign 5 to h[2]. It looks to me like you've found a bug. I can't think of any reason (and I really hope there isn't one, because having an exception to that ||= rule would be very messy) why using a default hash value would make any difference here. It's still 5 || 10 on the rhs, and it's still just an assignment.
unknown wrote: > x ||= y is, I think, always supposed to be exactly equivalent to > x = x || y, so that line in your first hash should be equivalent to:
> h[2] = 5 || 10
> which should assign 5 to h[2]. It looks to me like you've found a bug. > I can't think of any reason (and I really hope there isn't one, > because having an exception to that ||= rule would be very messy) why > using a default hash value would make any difference here. It's still > 5 || 10 on the rhs, and it's still just an assignment.
I don't think it's a bug; the two examples are set forth on p. 276 of "The Ruby Way (2nd ed)". However, no explanation is given for why the two examples work differently. -- Posted via http://www.ruby-forum.com/.
On Mon, 3 Sep 2007, 7stud -- wrote: > unknown wrote: >> x ||= y is, I think, always supposed to be exactly equivalent to >> x = x || y, so that line in your first hash should be equivalent to:
>> h[2] = 5 || 10
>> which should assign 5 to h[2]. It looks to me like you've found a bug. >> I can't think of any reason (and I really hope there isn't one, >> because having an exception to that ||= rule would be very messy) why >> using a default hash value would make any difference here. It's still >> 5 || 10 on the rhs, and it's still just an assignment.
> I don't think it's a bug; the two examples are set forth on p. 276 of > "The Ruby Way (2nd ed)". However, no explanation is given for why the > two examples work differently.
It seems very bug-like to me. I don't know what Hal's take on it is. Paging Hal....
> > Can someone explain why there is a difference in the second line of > > output for the two hashes:
> > h = Hash.new(5)
> > puts h[2]
> > h[2] ||= 10 > > p h
> > #---------- > > puts > > #----------
> > h = Hash.new
> > puts h[2]
> > h[2] ||= 10 > > p h
> > ---output:-- > > 5 > > {}
> > nil > > {2=>10}
> x ||= y is, I think, always supposed to be exactly equivalent to > x = x || y, so that line in your first hash should be equivalent to:
> h[2] = 5 || 10
> which should assign 5 to h[2]. It looks to me like you've found a bug. > I can't think of any reason (and I really hope there isn't one, > because having an exception to that ||= rule would be very messy) why > using a default hash value would make any difference here. It's still > 5 || 10 on the rhs, and it's still just an assignment.
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. :-)
Peña, Botp wrote: > they should be different (note, that has nothing to do w the bug dBlack > is pointing at) and the output should be,
> 5 > {2=>5} #<---dblack is complaining here because the ruby output is {}
> nil > {2=>10}
Yes. That is what I am complaining about too! Your are right: the second line for each section of the output should be different--I mispoke. What I want to know is why the the output is {} and not {2=>5}.
The author of "The Ruby Way (2nd ed)" presents the two examples as well as the different output for each example, yet he doesn't explain the reason for the different output. He suggests that you can use ||= to selectively assign values only to keys that don't exist. The point I think he was trying to make with the two examples is that when you have a default value for non-existent keys, all keys "exist", so ||= will not create new keys with the default value. -- Posted via http://www.ruby-forum.com/.
Peña, Botp wrote: > pls refer to the hash#new document.
I also have "Programming Ruby (2nd ed)", and I read the documentation therein for Hash.new many times before posting--which is the same documentation that ri produces.
On Mon, 3 Sep 2007, Robert Klemme wrote: > 2007/9/3, dbl...@wobblini.net <dbl...@wobblini.net>: >> Hi --
>> On Mon, 3 Sep 2007, 7stud -- wrote:
>>> Can someone explain why there is a difference in the second line of >>> output for the two hashes:
>>> h = Hash.new(5)
>>> puts h[2]
>>> h[2] ||= 10 >>> p h
>>> #---------- >>> puts >>> #----------
>>> h = Hash.new
>>> puts h[2]
>>> h[2] ||= 10 >>> p h
>>> ---output:-- >>> 5 >>> {}
>>> nil >>> {2=>10}
>> x ||= y is, I think, always supposed to be exactly equivalent to >> x = x || y, so that line in your first hash should be equivalent to:
>> h[2] = 5 || 10
>> which should assign 5 to h[2]. It looks to me like you've found a bug. >> I can't think of any reason (and I really hope there isn't one, >> because having an exception to that ||= rule would be very messy) why >> using a default hash value would make any difference here. It's still >> 5 || 10 on the rhs, and it's still just an assignment.
> 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. :-)
I still don't like it. I'm not sure about that "unless" thing.... I always thought x ||= y was strictly syntactic sugar for x = x || y. I'm now thinking about how much fun it will be to explain to people learning Ruby that that's true, unless the lhs is a call to Hash#[] on a hash with a default value with a boolean value of true, in which case...... What fun :-)
I wonder whether there's some special optimization for hashes. I can't find any other example where the setter method isn't called (except attr_accessor-created setters, which I haven't puzzled through yet). I won't paste the whole output but run this:
class C def x; @x; end def x=(x); @x = x; end end
c = C.new
set_trace_func lambda {|*a| p a } c.x ||= 1 puts c.x = nil puts c.x = c.x || 1 puts
a = [] puts a[1] ||= 1 puts a[2] = a[2] || 1
As far as I can tell, the sugar version and the inlined version work exactly the same, except for hashes.
[
multipart_mixed_part ] This message is in MIME format. The first part should be readable text, while the remaining parts are likely unreadable without MIME-aware tools.
On Mon, 3 Sep 2007, 7stud -- wrote: > Peña, Botp wrote: >> they should be different (note, that has nothing to do w the bug dBlack >> is pointing at) and the output should be,
>> 5 >> {2=>5} #<---dblack is complaining here because the ruby output is {}
>> nil >> {2=>10}
> Yes. That is what I am complaining about too! Your are right: the > second line for each section of the output should be different--I > mispoke. What I want to know is why the the output is {} and not > {2=>5}.
> The author of "The Ruby Way (2nd ed)" presents the two examples as well > as the different output for each example, yet he doesn't explain the > reason for the different output. He suggests that you can use ||= to > selectively assign values only to keys that don't exist. The point I > think he was trying to make with the two examples is that when you have > a default value for non-existent keys, all keys "exist", so ||= will not > create new keys with the default value.
I don't have the book at hand but the default value definitely doesn't mean that all keys exist (or even "exist" :-)
I don't think this is a bug, kittens. since h[2] returns a value [even though it's not set], it causes h[2] to evaluate so the assignment never happens. x ||= y just means give me x or set x to y if there's no value for x. h[2] _does_ have a value if only a default one.
just my two cents.
unless i missed the point here, in which case i apologize for my hasty conclusion. :))
> Peña, Botp wrote: > > pls refer to the hash#new document.
> I also have "Programming Ruby (2nd ed)", and I read the documentation > therein for Hash.new many times before posting--which is the same > documentation that ri produces.
unknown wrote: > The only possible explanation I can come up with, which I don't like, > is that:
> h[2] ||= 10
> is being treated like:
> 5 = 5 || 10
> which is just another can of worms.
I also considered that possibility. Does the trace output support that? I don't really know how to read the trace output, but it doesn't look like there are two calls to Hash#[] for each ||=. -- Posted via http://www.ruby-forum.com/.