Hi --
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] => #<struct Foo bar="Hello">
h[:furby] => #<struct Foo bar="Hello">
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] => #<struct Foo bar=nil>
h[:furby] => #<struct Foo bar=nil>
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=>#<struct Foo bar="Hello">}
h[:baz] => #<struct Foo bar="Hello">
h[:furby] => #<struct Foo bar=nil>
h => {:baz=>#<struct Foo bar="Hello">, :furby=>#<struct Foo bar=nil>}
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