2010-03-27 35 views
5

Aquí hay un código de ejemplo:¿Cómo funciona Ruby's Array? comparar elementos para la igualdad?

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] 

imprime 2 objetos pero debe imprimir 1 objeto. Ninguno de los métodos de comparación se llama. ¿Cómo es Array? comparando por la igualdad?

Respuesta

6

Array#| se implementa utilizando hashs. Entonces, para que su tipo funcione bien con él (así como también con hashsets y hashsets), tendrá que implementar eql? (que lo hizo) y hash (que no lo hizo). La forma más sencilla de definir el hash de manera significativa sería simplemente devolver c.hash.

+0

Solo para confirmar: ¿el método Ruby's Array # hash garantiza que los valores serán iguales si y solo si el contenido de las matrices es igual? –

+0

@EricWalker No. Se garantiza que los hashs de dos matrices son iguales si (pero no solo si) ambas matrices contienen elementos con los mismos valores hash en el mismo orden. Sin embargo, esto no está relacionado con esta pregunta, ya que aquí el hash solo se usa en los elementos, nunca en las matrices. – sepp2k

1

La clase Ruby's Array se implementa en C, y por lo que puedo decir, utiliza una tabla hash personalizada para comprobar la igualdad al comparar objetos en |. Si desea modificar este comportamiento, tendrá que escribir su propia versión que utilice una verificación de igualdad de su elección.

Para ver la plena aplicación de Ruby Array#|: click here y busque "rb_ary_or(VALUE ary1, VALUE ary2)"

0

Ruby está llamando a las funciones hash y están devolviendo valores diferentes, porque todavía están devolviendo el object_id predeterminado. Tendrá que llamar al def hash y devolver algo que refleje su idea de lo que hace que un Obj sea significativo.

>> class Obj2 < Obj 
>> def hash; t = super; p ['hash: ', t]; t; end 
>> end 
=> nil 
>> x, y, x.c, y.c = 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>] 
Cuestiones relacionadas