From: Alex Stahl Date: 2010-09-23T04:51:54+09:00 Subject: Re: Odd behavior when << hash Thanks, Rob. Made the mistake of assuming I get a copy of the hash when I push it. IIRC, there are other (not-so-elegant) languages that do so. Appreciate the point about .dup as well, but since at the end of this, I'm just writing everything out to a file, and the elements of ids will never change (at least not in this script), I don't think I need a duplicate string. On Wed, 2010-09-22 at 14:43 -0500, Rob Biedenharn wrote: > On Sep 22, 2010, at 3:33 PM, Alex Stahl wrote: > > > Hi Folks - Using Ruby 1.8.7, I found this oddity: > > > > require 'rubygems' > > require 'json' > > > > setup = [] > > ids = ["12345", "54321", "21345", "548752", "3215", "50203"] > > > > doIt = { > > "action" => "do something", > > "result" => "true" > > } > > > > # so here, doIt is referencing an object which is a hash > > > cnt = rand(10) > > 1.upto(cnt) do > > > > doIt['params'] = ids[rand(6)] > > p "Pushing step: #{doIt.inspect}" > > setup << doIt > > # this puts that reference into the setup array > # NOTE: it is always referring to the same hash > > > end > > > > p "Final steps list: #{setup.inspect}" > > > > ************************************** > > > > When I inspect my final steps list at the end, the values of > > 'doIt['params']' is always the same - set to the last value of the > > last > > run of the upto loop. But when I inspect doIt prior to pushing it, I > > can see that it has its own value, acquired randomly. > > > > So my question is, why is the hash not being pushed onto the array > > properly? What side effect am I encountering here and how do I get > > around it? > > > > (I've already tried declaring "params" => "" in the initial hash > > creation; that didn't help). > > > > Thanks, > > Alex > > > > PS - You'd be correct in noting this code doesn't do anything useful. > > I've stripped away other parts to isolate the questionable behavior > > for > > demonstration purposes. > > > > > > > Try creating the hash object inside the loop (i.e., creating a new > object each time) > > rand(10).times do > setup << { "action" => "do something", > "result" => "true", > "params" => ids[rand(6)].dup > } > end > puts "Final steps list: #{setup.inspect}" > > > Note that I'm also calling .dup on the element taken from the ids > array so there's a separate string object. You can apply this to your > real code, I hope. > > -Rob > > Rob Biedenharn > Rob@AgileConsultingLLC.com http://AgileConsultingLLC.com/ > rab@GaslightSoftware.com http://GaslightSoftware.com/ > >