From: Robert Klemme Date: 2011-10-25T23:45:44+09:00 Subject: Re: Unusual behavior of a Ruby hash On Tue, Oct 25, 2011 at 3:50 PM, Edmond Kachale wrote: > Rubysters, > > I had the following code working nicely: > > (a) http://pastie.org/private/8qn4f36mfeppbobm7b2wsa > > At the beginning of every iteration, I expect "essential_params" hash (in > line 8) to look like this: essential_params  = {:val_1 => 0, :val_2 => > [x,y,z], :val_3 =>0}. However it does repetitive work to initialize a hash > from a database (in line 8). > > So as to reduce repetitive database querying (at every iteration), I have > just moved hash initialization to (line 7) outside a loop: > > (b) http://pastie.org/private/iudfe0q2s41vszxby6vva > > Now the code acts wierd: At every iteration,  my "essential_params" hash > contains data accumulated from the previous iterations. For example, at the > nth iteration, essential_params may look like this: {:val_1 => 25, :val_2 => > [x,y,z], :val_3 =>24} which are results from (n-1)th iteration (instead of > the default values: {:val_1 => 0, :val_2 => [x,y,z], :val_3 =>0}). > > Does anyone have a better explanation about this? Are Ruby hashed assigned > by value or by reference? (Specifically, why is the pre-populated hash at > line 7 in (b) getting values from lines 22 and 23 ? ) Ruby only has object references (there are some internal optimizations but for now that is adequate). You have only one object which you reuse during every iteration. Hence during each iteration you will see modifications from previous iterations. A simplified example of what happens is this: irb(main):008:0> a = [] => [] irb(main):009:0> 4.times do |i| irb(main):010:1* printf "%d %-10s %p\n", i, "before", a irb(main):011:1> a << i irb(main):012:1> printf "%d %-10s %p\n", i, "after", a irb(main):013:1> end 0 before [] 0 after [0] 1 before [0] 1 after [0, 1] 2 before [0, 1] 2 after [0, 1, 2] 3 before [0, 1, 2] 3 after [0, 1, 2, 3] => 4 irb(main):014:0> a => [0, 1, 2, 3] You can also look at #object_id to see it's really the same object all the time. Kind regards robert -- remember.guy do |as, often| as.you_can - without end http://blog.rubybestpractices.com/