Maggie
Maggie

Reputation: 8081

comparison of Hash with Hash failed

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

Answers (2)

SRack
SRack

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

idmean
idmean

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

Related Questions