Welcome! Please see the About page for a little more info on how this works.

+4 votes
in Clojure by

user=> (case -1 -1 true false) true user=> (case [-1] [-1] true false) true user=> (case (int -1) -1 true false) true user=> (case [(int 1)] [1] true false) true user=> (case [(int -1)] [-1] true false) false

The last case should return true like the other,

Real life example that triggered this:

(case [">" (compare 2 3)] [">" -1] true false) ;; false?

Explaination: This is caused by case using hashCode instead of hashEq for hash comparisons (when not wrapped in a vector, the comparison is direct) and the fact that negative integers and negative longs hash differently while positive ones hash identical.
Porposal: Make case use hasheq instead of hashCode

Patch: 0001-switch-to-hasheq-for-case.patch

Just ran in to this problem yesterday, and took a while to figure out that this was the underlying issue.  In that code it was (-1 :x) rather than [-1 ...], but had the same result -- the wrong clause was chosen.  Coercing the incoming value to a long selected the correct clause (version 1.11.1).

Be very happy to see this fixed.

2 Answers

0 votes

Comment made by: bronsa

Patch is a straightforward search and replace, apart from line 30 of the diff which is quite tricky: I believe using h there was a bug in the previous impl that never survaced because hashCode on positive integers is idempotent. But since hashEq isn't double hashing would cause collision nodes never to match.

0 votes
Reference: https://clojure.atlassian.net/browse/CLJ-2275 (reported by alex+import)