Here's some example code:
class Obj
attr :c, true
def == that
p '=='
that.c == self.c
end
def <=> that
p '<=>'
that.c <=> self.c
end
def equal? that
p 'equal?'
that.c.equal? self.c
end
def eql? that
p 'eql?'
that.c.eql? self.c
end
end
a = Obj.new
b = Obj.new
a.c = 1
b.c = 1
p [a] | [b]
It prints 2 objects but it should print 1 object. None of the comparison methods get called. How is Array.| comparing for equality?
Ruby's Array class is implemented in C, and from what I can tell, uses a custom hash table to check for equality when comparing objects in
|
. If you wanted to modify this behavior, you'd have to write your own version that uses an equality check of your choice.To see the full implementation of Ruby's
Array#|
: click here and search for "rb_ary_or(VALUE ary1, VALUE ary2)
"Ruby is calling the hash functions and they are returning different values, because they are still just returning the default object_id. You will need to
def hash
and return something reflecting your idea of what makes an Obj significant.Array#|
is implemented using hashs. So in order for your type to work well with it (as well as with hashmaps and hashsets), you'll have to implementeql?
(which you did) andhash
(which you did not). The most straight forward way to define hash meaningfully would be to just returnc.hash
.