UPDATE: In the comments, Kent has provided a complete solution to this problem:

hash = Hash.new(&(p=lambda{|h,k| h[k] = Hash.new(&p)}))


I would love to see this integrated in to the Hash class at some point, but if not, we can (with Ruby’s kind acceptance) do it ourselves:

class Hash
  def self.arbitrary_depth
    Hash.new(&(p=lambda{|h,k| h[k] = Hash.new(&p)}))
  end
end


Thus,

hash = Hash.arbitrary_depth


While working on FamilyLearn.com today, I ran in to an interesting Ruby puzzle–how do you create a PHP-like Hash object that accepts keys to an arbitrary depth?For example, the following will not work in Ruby:
h = Hash.new
h[:one][:two] = "uh-oh!"
# NoMethodError: undefined method `[]=' for nil:NilClass

The solution? Pass in a proc that will tell Hash to create a second hash by default for each key that is not found:

h = Hash.new { |h,v| h[v]= Hash.new }
h[:one][:two] = "uh-oh!"
# => "uh-oh!"
h
# => {:one=>{:two=>"uh-oh!"}}

Much better. But that’s only two-deep. What about n-deep? The solution I found isn’t fully “arbitrary” on demand, but it should work for most cases:

class ArbitraryDepthHash
  def self.arbitrary_depth_proc(depth = 1)
    proc { |h,v| h[v] = Hash.new(&arbitrary_depth_proc(depth-1)) }
  end

  def self.[](depth)
    Hash.new(&arbitrary_depth_proc(depth))
  end
end

h = ArbitraryDepthHash[5]
h[:one][:two][:three][:four][:five] = "wow!"
# => "wow!"
h
# => {:one=>{:two=>{:three=>{:four=>{:five=>"wow!"}}}}}