[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

assigning to hash keys when there is a default value?

7stud 7stud

9/3/2007 1:54:00 AM

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}
--
Posted via http://www.ruby-....

37 Answers

dblack

9/3/2007 2:19:00 AM

0

7stud 7stud

9/3/2007 2:29:00 AM

0

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-....

dblack

9/3/2007 10:24:00 AM

0

Robert Klemme

9/3/2007 11:09:00 AM

0

2007/9/3, dblack@wobblini.net <dblack@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. :-)

Note also:

$ ruby -e 'h=Hash.new 2;set_trace_func lambda {|*a| p a}; h[4]||=10'
["line", "-e", 1, nil, #<Binding:0x1002ff48>, false]
["c-call", "-e", 1, :[], #<Binding:0x1002ff0c>, Hash]
["c-call", "-e", 1, :default, #<Binding:0x1002fdf4>, Hash]
["c-return", "-e", 1, :default, #<Binding:0x1002fcf0>, Hash]
["c-return", "-e", 1, :[], #<Binding:0x1002fc00>, Hash]

$ ruby -e 'h=Hash.new 2;set_trace_func lambda {|*a| p a}; h[4]=h[4]||10'
["line", "-e", 1, nil, #<Binding:0x1002fee4>, false]
["c-call", "-e", 1, :[], #<Binding:0x1002fea8>, Hash]
["c-call", "-e", 1, :default, #<Binding:0x1002fd90>, Hash]
["c-return", "-e", 1, :default, #<Binding:0x1002fc8c>, Hash]
["c-return", "-e", 1, :[], #<Binding:0x1002fb9c>, Hash]
["c-call", "-e", 1, :[]=, #<Binding:0x1002faac>, Hash]
["c-return", "-e", 1, :[]=, #<Binding:0x1002f9bc>, Hash]

There is no assignment in the first piece.

Kind regards

robert

7stud 7stud

9/3/2007 11:22:00 AM

0

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-....

7stud 7stud

9/3/2007 11:27:00 AM

0

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.

--
Posted via http://www.ruby-....

dblack

9/3/2007 11:33:00 AM

0

dblack

9/3/2007 11:37:00 AM

0

Russell Norris

9/3/2007 11:38:00 AM

0

I don't think this is a bug, kittens. since h[2] returns a value [eventhough it's not set], it causes h[2] to evaluate so the assignmentnever happens. x ||= y just means give me x or set x to y if there'sno 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 hastyconclusion. :))RSLOn 9/3/07, 7stud -- <dolgun@excite.com> wrote:> 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.>> --> Posted via http://www.ruby-forum.com...

7stud 7stud

9/3/2007 11:47:00 AM

0

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-....