On 7/15/11 6:04 PM, Robert Klemme wrote:

>> 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
>
> It seems your spec is not very precise because your bullet list mixes
> AND and OR.  I assume you meant
>
> Two objects o1 and o2 are considered equal for this relation if and only if
>
> ( o1 is nil AND o2 is nil ) OR
> ( o1 is a Hash AND o2 is a Hash AND
>    o1.keys == o2.keys AND
>    for each key k ( o1[k] is not a Hash OR
>                            o2[k] is not a Hash OR
>                            o1[k] equals o2[k] according to this relation ) )

Exactly.
Sorry about the confusion.

>> def compare(hash1, hash2)
>
> I would rename arguments because these need not be Hashes.

Fair enough.

>>   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
>
> Hm, I'd probably remove #all?, #any? and the like and code conditions
> directly - especially since you are always dealing with two items
> because it's likely faster.  Your code creates a lot of temporary
> Arrays along the way.

True.
On the other hand, the hashes will be fairly small, so performance 
wasn't the main goal.

That, and I the fact that I find:

	[x, y].all? {|x| x.is_a?(Hash) }

to be a bit more nice-looking than

	if x.is_a?(Hash) && y.is_a?(Hash)

But you make a very good point, thanks.

> Btw, I believe your implementation misses the case where hash2's key
> set is a superset of hash1's, i.e. contains additional keys.

True. I posted again the link to the gist with a revised version 
according to Rob's suggestions.


Thank you very much, Robert.
Ah, there are so many things to learn.

-- 
Stefano Mioli