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

Let us know how we can contact you.

Thank you!

We'll respond shortly.

LABS
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 *