Close
Glad You're Ready. Let's Get Started!

Let us know how we can contact you.

Thank you!

We'll respond shortly.

  • Blog Navigation
Equality and sameness in Ruby

Let’s say you are building a leetspeak that deals with w00ts. You might write a class that looks like this:

class Woot
  def ==(other)
    true
  end
end

In theory, any Woot is equal to anything else:

puts Woot.new == Woot.new # true

You might think that with this setup, you could do something like this:

x = [ Woot.new ]
y = [ Woot.new ]
z = x - y

You might expect z to be an empty array in the case, but oh how wrong you would be. In the example above, the == is never called at all.

After reading through the docs on Array, overriding all 4 equals method in ruby (eql?, equal?, ==, ===) and overriding object_id you will still not be able to make it work.

A quick look through the C code shows that Array#- hashifies the array. The hashing algorithm looks for a method called “hash” on the object. If that’s not there, it uses the memory id. Great, so now we can just add hash and be done, like this:

class Woot
  def ==(other)
    true
  end

  def hash
    1
  end
end

Wrong! You still don’t get an empty array. It turns out that the hash algorithm calls eql?, not ==, so you have to make sure to alias that as well, like so:

class Woot
  def ==(other)
    true
  end
  alias :eql? :==

  def hash
    1
  end
end

So if you want normal array semantics for your objects, be sure to provide #hash, #== and #eql?.

Comments
  1. grosser says:

    crazy but very helpful :D

Post a Comment

Your Information (Name required. Email address will not be displayed with comment.)

* Copy This Password *

* Type Or Paste Password Here *

Share This