On 5/21/21 2:55 PM, Knut Alejandro Anderssen González wrote:
## Short version or Reminder
Any subclass that overrides 'eql?' should also override 'hash'
appropriately.
By default, the methods #==, #eql? and #equal? in Object subclasses
return true if both objects are the same (point to the same object in
memory). Well, actually #eql? should return true if both objects refer
to the same hash key. But in practice, two objects have the same hash
key if they are the very same object. There are some exceptions like
String, which returns the same hash key if they have the same value.
The #eql? and #hash methods must be related. That is, if two objects are
#eql?, then they should have the same #hash. This is important,
otherwise we could have unexpected results in certain operations like
subtracting Arrays. When performing the difference of two Arrays, the
method used for comparing the objects in the Array depends on the Array
length (see source code of Array#difference [1]). If both Arrays have
more than SMALL_ARRAY_LEN (i.e., 16) elements, then the #hash method is
used. Otherwise it uses #eql?. This is one of the reason why #eql? and
#hash should be paired.
In YaST code, we tend to overload #== and then to make #eql? an alias to
the overloaded #==. This is dangerous if we forget to modify #hash
properly. For example, the result of Array<OurClass> - Array<OurClass>
would depend on the length of the arrays.
To avoid these problems, I think we should keep the same logic for #eql?
and #hash. And optionally, we could do #== an alias to #eql?.
I have prepared a proposal in yast-users [2]. It consists on a mixing to
implement the "Equatable" property. What do you think? If you agree with
this solution (or something) similar, then we could move it to a more
generic place like yast2 repo.
Regards,
Iván
[1] https://ruby-doc.org/core-2.7.0/Array.html#method-i-difference
[2] https://github.com/yast/yast-users/pull/283/files
--
José Iván López González
YaST Team at SUSE LINUX GmbH
IRC: jilopez