You don't need access to the original hash definition -- you can override the [] method on the fly after you get it using h.instance_eval, e.g.
h = {1 => 'one'}
h.instance_eval %q{
alias :brackets :[]
def [] key
if self.has_key? key
return self.brackets(key)
else
h = Hash.new
h.default = {}
return h
end
end
}
But that's not going to help you with the code you have, because you're relying on an unfound value to return a false value (e.g., nil) and if you do any of the "normal" auto-vivification stuff linked to above you're going to end up with an empty hash for unfound values, which evaluates as "true".
You could do something like this -- it only checks for defined values and returns them. You can't set them this way, because we've got no way of knowing if the call is on the LHS of an assignment.
module AVHash
def deep(*args)
first = args.shift
if args.size == 0
return self[first]
else
if self.has_key? first and self[first].is_a? Hash
self[first].send(:extend, AVHash)
return self[first].deep(*args)
else
return nil
end
end
end
end
h = {1=>2, 3=>{4=>5, 6=>{7=>8}}}
h.send(:extend, AVHash)
h.deep(0) #=> nil
h.deep(1) #=> 2
h.deep(3) #=> {4=>5, 6=>{7=>8}}
h.deep(3,4) #=> 5
h.deep(3,10) #=> nil
h.deep(3,6,7) #=> 8
Again, though, you can only check values with it -- not assign them. So it's not real auto-vivification as we all know and love it in Perl.
?
operator. Actually i'm interested by an equivalent operator. You can still extend the hash class and add the operator. – Motherofpearl