From: Gary Wright Date: 2011-09-16T06:42:17+09:00 Subject: Re: Some newbie questions On Sep 15, 2011, at 3:46 PM, Vladimir Van Bauenhoffer wrote: > 2. Hash.new {0} > anotherhash.values.each {|x| thecreatedhash[x] += 1} > > What makes the hash created above different from a hash created the > normal way? I can execute the block on a hash created with that method > but not a normal empty hash created manually. A hash created via a literal: hash1 = {} has a default value of nil: hash1['foo'] # returns nil A hash created as you suggested: hash2 = Hash.new { 0 } *computes* a value whenever the key lookup fails. In this case the computation is the trivial expression: 0 but it could be something arbitrarily complicated and can depend on the key itself hash3 = Hash.new { |hash, key| hash[key] = key.reverse } hash3['hello'] # returns 'olleh' If you want the returned value to be saved for future lookups with the same key, then you have to store the value in the hash explicitly as shown above. Otherwise a new value will be recomputed for each key lookup (even for multiple lookups of the same key). If you just want a hash that defaults to 0 for missing keys then you don't really need the block form where you 'compute' zero each time. Use this form instead: hash4 = Hash.new(0) hash4[42] # returns 0 Be careful with this form though because it is the exact same object that is returned for the value of *all* missing keys: hash5 = Hash.new([]) # an array is allocated here and used for all missing keys apple = hash5['apple'] # the array allocated and passed to Hash.new banana = hash5[banana'] # the same array! apple.equal?(banana) # true In this case, you almost always want to allocate a brand new array for each key miss. Time to go back to the block format: hash6 = Hash.new {|h,k| h[k] = [] } # allocate a brand new array for each key miss Gary Wright