Hi list,
     let's say we want to write a method that compares two hashes for 
equality based on their keys.

Each key is a symbol, and the corrisponding value can either be a string 
or another hash with this same properties.

Two hashes, let's call them h1 and h2, are to be considered equal if:

* they have the same keys

* h1[:x] and h2[:x] are both hashes, and they are equal according to the 
very same rules you are reading ;)

* they are both nil

In short, we only care about the values when they are hashes.
If they are strings, we don't care whether they are equal or not.

To make an example, when fed these two hashes the method should return true:

h1 = {
   :one => "one",
   :two => "two",
   :three => {
     :alpha => "alpha",
     :bravo => "bravo",
     :charlie => "charlie"
   }
}

h2 = {
   :one => "whatever",
   :two => "hey",
   :three => {
     :alpha => "zulu",
     :bravo => "oscar",
     :charlie => "brown"
   }
}

When fed these other two arrays, the method should return false:

h3 = h1

h4 = {
   :one => "one",
   :two => "two",
   :three => {
     :alpha => "alpha",
     :bravo => "bravo",
   }
}

The difference is that Ole :charlie is missing in h2.
The values don't change to make it clear that we don't care about them.

I came up with the following implementation that seems to work (at least 
according to the specs I wrote), but what I would like to ask is if it 
could be any simpler/more idiomatic/more elegant.

Corner cases that one might spot are also good to know about.

def compare(hash1, hash2)
   args = [hash1, hash2]

   return true if args.all? {|h| h.nil?}
   return false if args.one? {|h| h.nil?}

   hash1.each_key do |k|
     values = [hash1[k], hash2[k]]

     if values.all? {|h| h.is_a?(Hash)}
       return compare(*values)
     else
       return false if values.one? {|value| value.nil? }
     end
   end

   true
end


Should the code turn out to be unreadable, I posted it here[0] too.

[0] = https://gist.github.com/1084916


Thanks in advance.

-- 
Stefano