From: Ken Bloom Date: 2007-11-04T11:40:47+09:00 Subject: Re: x=[]; x[:bla][:some_key] does not work? On Sat, 03 Nov 2007 20:46:00 -0500, dblack wrote: > Hi -- > > On Sun, 4 Nov 2007, Ken Bloom wrote: > >> sepp2k's answer is the only correct answer in this thread. > > Could you point out the mistakes in my answers for me? I'd be > interested. Thanks -- > > > David The Hash.new constructor has several different behaviors depending on what you pass it: Hash.new(param) creates a new hash where the object in param is returned whenever a specific key is not found. No new key is created in the hash: a=Hash.new(0) => {} a[:foo] => 0 a => {} Additionally, this same object is constructed once, and used every time you call the hash so: Foo=Struct.new(:bar) => Foo h=Hash.new(Foo.new) => {} h[:baz].bar="Hello" => "Hello" h => {} h[:baz] => # h[:furby] => # I haven't created any keys, here, but I've changed the default value of the hash. Hash.new{code} creates a new hash where default values are generated by executing the block {code}. When used as Hash.new{param} the code inside the block is called every time, and a new object is constructed every time. (because {} and [] construct a new object every time they are encountered in execution, here they are encountered every time the block is called, whereas before they were encountered only once when the hash was constructed). But the semantics of key creation are the same as before -- no new keys are created until you explicitly assign to the hash. a=Hash.new{0} => {} a[:foo] => 0 a => {} Foo=Struct.new(:bar) => Foo h=Hash.new{Foo.new} => {} h[:baz].bar="Hello" => "Hello" h => {} h[:baz] => # h[:furby] => # Hash.new{|h,k| h[k]=param} this finally assigns to the hash when you access the hash. Foo=Struct.new(:bar) => Foo h=Hash.new{|h,k| h[k]=Foo.new} => {} h[:baz].bar="Hello" => "Hello" h => {:baz=>#} h[:baz] => # h[:furby] => # h => {:baz=>#, :furby=>#} Personally, I think that Hash might benefit from having a few more named constructors so that people can guess the expected behavior by name. Particularly one that automatically does the whole Hash.new{|h,k| h[k]=param} thing, through judicious use of #dup. class Hash def self.new_add obj Hash.new{|h,k| h[k]=obj.dup} end end -- Ken Bloom. PhD candidate. Linguistic Cognition Laboratory. Department of Computer Science. Illinois Institute of Technology. http://www.iit.edu/~kbloom1/