Details
-
Type:
Defect
-
Status:
Open
-
Priority:
Major
-
Resolution: Unresolved
-
Affects Version/s: Release 1.4
-
Fix Version/s: None
-
Component/s: None
-
Labels:None
-
Patch:Code and Test
-
Approval:Not Approved
Description
The doc string for hash states that it defines a hash code function that is consistent with =, but for java.math.BigInteger hash is not consistent with =.
user=> (apply = [(Long. -1) -1N (biginteger -1)]) true user=> (map hash [(Long. -1) -1N (biginteger -1)]) (0 0 -1) user=>
It is possible to have a PHM with two key/value pairs where the keys are equal, and the hash codes are different:
user=> (assoc clojure.lang.PersistentHashMap/EMPTY (biginteger -1) :oops! -1N :one)
{-1N :one, -1 :oops!}
The expected behavior is the same as PersistentArrayMap, which does not have this issue, because it does not hash its keys:
user=> (assoc clojure.lang.PersistentArrayMap/EMPTY (biginteger -1) :oops! -1N :one)
{-1 :one}
This same misbehavior also occurs for Doubles and Floats:
thalia.core=> (apply = [(Float. 1e9) (Double. 1e9)]) true thalia.core=> (map hash [(Float. 1e9) (Double. 1e9)]) (1315859240 1104006501)
That leads to the same difference in array-map and hash-map behavior as above for BigInteger and BigInt.
Also, the biginteger function has metadata saying that it has been added since 1.0, but it was actually added in 1.3. The bigint function has metadata saying that it has been added since 1.3, but it has been added since 1.0.
I think during the work to implement BigInt someone renamed the existing bigint function (which used to return a BigInteger) to biginteger, and the metadata got carried with it, then a new bigint function was added with :since 1.3 metadata even though that function name has existed since 1.0.