Hello --

On Sat, 7 Jul 2001, Guillaume Cottenceau wrote:

> Hi,
>
>
> I have a loop in which I'd like to populate a Hash by pushing back new
> elements to Arrays.
>
> The problem is when I try to push back an element, because the default
> element "references" the default, which is an empty array, the action is
> only to make the default enlarges, not what I want :-).

[...]

> Does someone has the magical solution? Apart of course using nil (or
> anything) as default value, and testing for existence of key before each
> pushing, possibly allocating a new Array.
>
> As far as I looked, the default value must be an object, it can't be set
> to something callable (proc) each time we need the default.

For what it's worth, here's something I wrote a few months ago as a
kind of testbed for this.  There was a bunch of discussion on this
list around that time (about January).  I've added a test for your
particular case.  This might at least provide a starting point for
exploring.  I'm not sure what the status of Hash#default's future is
(there were certainly suggestions for change/enhancement).

   class Hash
     alias :oldinit :initialize
     alias :olddef :default
     alias :oldget :[]

     attr_accessor :block

     def initialize(*d, &b)
       self.block = b || false
       oldinit(*d)
     end

     def default(arg)
       if block
	 block.call(self, arg)
       else
	 od = olddef
	 if od.is_a? Proc then od.call else od end
       end
     end

     def [](k)
       has_key?(k) ? oldget(k) : self[k] = default(k)
     end
   end

   def testme
     a = Hash.new(Proc.new { [] })
     a["banana"].push(1)
     p a
     a["apple"].push(2)
     p a
   end

   testme

__END__


David

-- 
David Alan Black
home: dblack / candle.superlink.net
work: blackdav / shu.edu
Web:  http://pirate.shu.edu/~blackdav