How Ruby Array Works | compare items for equality?

Here is a sample 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 ac = 1 bc = 1 p [a] | [b] 

It prints 2 objects, but must print 1 object. None of the comparison methods are called. What does an array look like? comparison for equality?

+5
source share
3 answers

Array#| implemented using hashes. Therefore, for your type to work well with it (as well as with hashmaps and hashsets), will you have to implement eql? (what you did) and hash (which you did not). The most direct way to determine the hash would be to simply return c.hash .

+6
source

The Ruby Array class is implemented in C, and from what I can say, it uses a custom hash table to check for equality when comparing objects in | . If you want to change this behavior, you will have to write your own version that uses the equality check of your choice.

To see the full implementation of Ruby Array#| : click here and find " rb_ary_or(VALUE ary1, VALUE ary2) "

+1
source

Ruby calls hash functions, and they return different values ​​because they still just return the object_id object by default. You need to def hash and return something that reflects your idea of ​​what makes the value of Obj significant.

 >> class Obj2 < Obj >> def hash; t = super; p ['hash: ', t]; t; end >> end => nil >> x, y, xc, yc = Obj2.new, Obj2.new, 1, 1 => [#<Obj2:0x100302568 @c=1>, #<Obj2:0x100302540 @c=1>, 1, 1] >> p [x] | [y] ["hash: ", 2149061300] ["hash: ", 2149061280] ["hash: ", 2149061300] ["hash: ", 2149061280] [#<Obj2:0x100302568 @c=1>, #<Obj2:0x100302540 @c=1>] 
0
source

All Articles