Reputation: 8081
Today I encountered an interesting issue:
When sorting an array of hashes, it fails with an error comparison of Hash with Hash failed
. Example:
h1 = {a:1, b:2}
h2 = {a:1, b:3}
[h1, h2].sort ArgumentError: comparison of Hash with Hash failed
now, the weird thing is that both ==
and eql?
succeed normally.
h1==h2
=> false
h1.eql?(h2)
=> false
What's even more weird is that the sort on the array succeeds if the hashes are the same:
h1= {a:1, b:2}
h2= {a:1, b:2}
[h1, h2].sort
=> [{:a=>1, :b=>2}, {:a=>1, :b=>2}]
I assume array sort doesn't use eql?
internally. What does it use? Any explanation into why this is happening?
Upvotes: 3
Views: 4507
Reputation: 12203
Sort uses the spaceship operator <=>
. The docs state:
... comparison between a and b and return an integer less than 0 when b follows a, 0 when a and b are equivalent, or an integer greater than 0 when a follows b
When you run the following, it returns nil:
{a:1, b:2} <=> {a:1, b:3}
#=> nil
Whereas if you do the same with an array, you get the correct result:
[1] <=> [2]
#=> -1
[2] <=> [2]
#=> 0
[3] <=> [2]
#=> 1
Hence the sort not working, as far as I'm aware.
As for the latter case, an array of equal hashes, I wonder if the method does an equality check before the sorting. I've had a look at the source, though don't know C, so perhaps someone more knowledgeable can confirm or refute this.
Upvotes: 0
Reputation: 14875
Sorting depends on the ability to determine whether something is smaller, larger or equal, which is described as Comparable.
Hash is not comparable and calling <=>
with two hashes returns nil.
Upvotes: 3