From: gwtmp01@... Date: 2006-01-26T23:02:56+09:00 Subject: Re: Hash with array as value type On Jan 26, 2006, at 6:22 AM, Michael McGreevy wrote: > I am new to ruby, so maybe I am just doing something stupid (... I am > not sure about that "Hash.new( [] )" for example... ) > Can anyone explain these results? It is a bit confusing. Hash.new([]) tucks away the newly created array as the default value: d = [] puts d.object_id hash1 = Hash.new(d) puts hash1.default.object_id You can see from this that Hash has saved a reference to the default value. So when you call: hash1["hello"].push(1.0) on the empty hash, a reference to the default value is returned because the key is not found. The float, 1.0, is pushed onto that default value. You still haven't entered anything into the Hash itself but you have pushed a value into the default array: puts hash1.default This same default object will be returned each time a lookup fails in the Hash. The solution is to use the block form of the Hash constructor. hash1 = Hash.new { |h,k| h[k] = [] } In this form, every lookup miss causes the block to be called with the hash and the key as the two arguments. The block allocates a new array and then stores it back into the hash using the key so that the next lookup finds the newly allocated array and doesn't call the block. Here is your example rewritten with that and adjusted to follow the usual ruby coding styles: hash1 = Hash.new { |h,k| h[k] = [] } hash1["hello"].push(1.0) hash1["hello"].push(2.0) warn("hash1.size = #{hash1.size}") warn("hash1.empty? = #{hash1.empty?}") warn("hash1[\"hello\"].size = #{hash1["hello"].size}") warn("hash1[\"hello\"] = #{hash1["hello"]}") warn("") hash2 = {"hello" => [1.0,2.0]} warn("hash2.size = #{hash2.size}") warn("hash2.empty = #{hash2.empty?}") warn("hash2[\"hello\"].size = #{hash2["hello"].size}") warn("hash2[\"hello\"] = #{hash2["hello"]}") Gary Wright