From: Warren Brown Date: 2003-02-21T03:27:27+09:00 Subject: Inconsistent behavior in Array methods I recently tracked down a bug in my code to a line that read: cards = cards.sort.uniq This seemed perfectly reasonable - the cards array contained Card objects which were Enumerable. However, the bug was due to the fact that Array#uniq does not use the object's == method to do comparisons - even though Array#sort uses the object's <=> method. Upon investigation, I found that the implementation of Array#uniq uses a hash, and since the key to the hash is the object ID, uniqueness ends up being defined as (obj1.id == obj2.id). This was *surprising* to me. Further investigation shows that the following methods of Array ignore the object's == method: Array#& Array#| Array#uniq Array#uniq! On the other hand, the following methods honor the object's == method: Array#- Array#== Array#=== Array#assoc Array#delete Array#include? Array#index Array#rassoc Array@rindex In addition, the following functions honor the object's <=> method: Array#<=> Array#sort Array#sort! Not only does this cause an inconsistency between the definition of equality between "set intersection" (Array#&) and "set difference" (Array#-), it also leads to different behavior between Numerics (and Strings) and other objects: irb(main):001:0> RUBY_VERSION => "1.6.8" irb(main):002:0> class A irb(main):003:1> def initialize(i) @i = i end irb(main):004:1> def ==(j) @i == j end irb(main):005:1> end => nil irb(main):006:0> [1,1,2].uniq => [1, 2] irb(main):007:0> ['1','1','2'].uniq => ["1", "2"] irb(main):008:0> [A.new(1),A.new(1),A.new(2)].uniq => [#, #, #] It seems to me that uniqueness should be determined by the object's == method instead of the object's ID as in Array#&, Array#|, Array#uniq, and Array#uniq!. This seems more in line with methods like Array#- and Array#include?. Any other thoughts? - Warren Brown