From: George Ogata Date: 2002-10-09T21:11:35+09:00 Subject: Re: strange Hash default behaviour Gavin Sinclair wrote: > From: "John Tromp" >> [all code snipped] >> but unfortunately, the default value [] for the Hash is shared by all >> elements, rather than copied, as I expected. >> >> I was wondering if this was a conscious design decision, or an oversight. >> I finally ended up with the much uglier >> >> Is there another way to avoid the explicit tests? > > > It's a common problem (are you listening, Bill :). > > I don't know about the design decision, but can offer a nicer solution. > Others will undoubtably have others; I remember there being some clever > ones expressed in the past, but not what they are :( > > Anyway: > > (hash[key] ||= []) << value > > Make sense? > > Gavin This seems similar to the problem with Array.new: Array.new(5, []) will put the same "[]" in each cell, so: a = Array.new(5, []) a[2] << 3 a # [[3],[3],[3],[3],[3]] If you're using 1.7?+, you can give a block to the constructor which is evaluated to get the value of each cell: a = Array.new(5) {[]} a[2] << 3 a # [[],[],[3],[],[]] A similar thing seems to exist for Hash: h = Hash.new([]) h[:a] <<= :x h[:b] <<= :y h[:a] #[:x, :y] h = Hash.new {[]} h[:a] <<= :x h[:b] <<= :y h[:a] # [:x] Strange thing is I can't find this documented anywhere. Not even at http://www.pragmaticprogrammer.com/ruby/new_features.html. Shouldn't this be added there?