2009/2/28 AD60 <andredeen / gmail.com>: > Hi, > > I am puzzled by the workings a the following program. I placed the > output after the corresponding lines. To me it lookes like a sort of > bug in the workings of de p method. Can anybody set me straight? There's no bug involved. > h = Hash.new([]) Here you create Hash with an empty array as default value. For every lookup of a key that is not in the hash, this single array instance is returned, but not automatically stored in the hash. Again: It's a single object, not a new one on every lookup. > h[0] = [1,2,3] Here you associate 0 with an array. The hash default value is not involved. > p h #> {0=>[1, 2, 3]} > h[0] += [4] > p h #> {0=>[1, 2, 3, 4]} This is a syntactic shortcut for "h[0] = h[0] + [4]". It looks up the value of 0 in the hash, which is an array. array + array creates a new array, which overwrites the previous value of h[0]. > h[1] += [10,11] > p h #> {0=>[1, 2, 3, 4], 1=>[10, 11]} Again, this is a shortcut for "h[1] = h[1] + [10, 11]". The hash doesn't have a value for 1 yet, so the default value ([]) is returned. [] + [10, 11] is the new array [10, 11] which is then assigned to h[1]. > h[1] << 12 > p h #> {0=>[1, 2, 3, 4], 1=>[10, 11, 12]} Look up the existing array stored in h[1] and append 12. No new array created. > h[2] << 20 > p h #> {0=>[1, 2, 3, 4], 1=>[10, 11, 12] ? The hash doesn't have a value for 2, so the default value, [], is returned. The default value is destructively modified by appending 20. _No new hash entry is created (there is no assignment!)._ Future lookups of non-existent keys will return the modified default value! > p h[2] #> [20] ??? The hash still doesn't have an entry for 2, so the default value is returned, which by now is our modified array. > h[2] << 21 > p h #> {0=>[1, 2, 3, 4], 1=>[10, 11, 12]} ? Still no entry for 2, default value is returned and modified by appending 21. > h[2] += [22] > p h #> {0=>[1, 2, 3, 4], 1=>[10, 11, 12], 2=>[20, 21, 22]} ???????? Again, this is equivalent to "h[2] = h[2] + [22]". Still no entry for h[2], so the default value is returned, which by now is [20, 21]. Then the two arrays [20, 21] and [22] are concatenated, returning the new array [20, 21, 22] which is then finally associated with 2 in the hash (see: here is an assignment!). What you probably want to achieve can be done using Hash's block constructor: h = Hash.new { |hash, key| hash[key] = [] } This automatically stores a new empty array on every lookup of a non-existent key. HTH, Stefan