On Feb 8, 3:00 pm, "Phrogz" <g... / refinery.com> wrote:
> On Feb 8, 2:29 pm, mike.le... / gmail.com wrote:
>
>
>
> > I am having problems understanding the following:
>
> > $ irb
> > irb(main):001:0> VERSION
> > => "1.8.5"
> > irb(main):002:0> a={:c => nil, :d => nil}
> > => {:c=>nil, :d=>nil}
> > irb(main):003:0> b={:d => nil, :c => nil}
> > => {:c=>nil, :d=>nil}
> > irb(main):004:0> # As expected this is true
> > irb(main):005:0* a == b
> > => true
> > irb(main):006:0> c={:a => nil, a => nil, :b => nil}
> > => {:b=>nil, :a=>nil, {:c=>nil, :d=>nil}=>nil}
> > irb(main):007:0> d={:b => nil, b => nil, :a => nil}
> > => {:b=>nil, {:c=>nil, :d=>nil}=>nil, :a=>nil}
> > irb(main):008:0> # Unexpectedly false
> > irb(main):009:0* c == d
> > => false
>
> > Shouldn't they be equivalent ?
>
> Let's make your example a little bit simpler to get at the core of the
> matter:
>   a = {}
>   b = {}
>   p a==b
>   #=> true
>
>   c = {1=>a}
>   d = {1=>b}
>   p c==d
>   #=> true
>
>   e = {a=>1}
>   f = {b=>1}
>   p e==f
>   #=> false
>
> Apparently it's enough for two values to be #== to one another, but
> it's not good enough for two keys to be #== to one another.

To take it one step further, think about it this way:
  p c[1] == d[1]
  #=> true

  p e[a] == f[a]
  #=> false

If you wanted the functionality you were expecting, then for these two
hashes:
  x = { m=>1, n=>2, o=>3 }
  y = { g=>1, h=>2, k=>3 }
testing for equality would have to do something like:

class Hash
  # Ouch! O(n^2) performance
  # Very bad for hashes with many keys
  def sort_of_equal( other )
    equal = true
    self.each{ |k,v|
      found_key=false
      other.each{ |k2,v2|
        found_key ||= ( ( k==k2 )  && ( v==v2 ) )
      }
      equal &&= found_key
    }
    equal
  end
end

p e.sort_of_equal( f )
#=> true