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.
Attachments
Activity
Andy Fingerhut
made changes -
| Field | Original Value | New Value |
|---|---|---|
| Attachment | clj-1036-hasheq-for-biginteger-patch-v1.txt [ 11524 ] |
Andy Fingerhut
made changes -
| Patch | Code and Test [ 10002 ] |
Stuart Halloway
made changes -
| Approval | Screened [ 10004 ] |
Rich Hickey
made changes -
| Approval | Screened [ 10004 ] | Not Approved [ 10008 ] |
Andy Fingerhut
made changes -
| Attachment | clj-1036-hasheq-for-biginteger-patch-v2.txt [ 11674 ] |
Andy Fingerhut
made changes -
| Attachment | clj-1036-hasheq-for-biginteger-patch-v1.txt [ 11524 ] |
Andy Fingerhut
made changes -
| Approval | Not Approved [ 10008 ] | Vetted [ 10003 ] |
Andy Fingerhut
made changes -
| 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 {{=}}.
{noformat} user=> (apply = [(Long. -1) -1N (biginteger -1)]) true user=> (map hash [(Long. -1) -1N (biginteger -1)]) (0 0 -1) user=> {noformat} It is possible to have a PHM with two key/value pairs where the keys are equal, and the hash codes are different: {noformat} user=> (assoc clojure.lang.PersistentHashMap/EMPTY (biginteger -1) :oops! -1N :one) {-1N :one, -1 :oops!} {noformat} The expected behavior is the same as PersistentArrayMap, which does not have this issue, because it does not hash its keys: {noformat} user=> (assoc clojure.lang.PersistentArrayMap/EMPTY (biginteger -1) :oops! -1N :one) {-1 :one} {noformat} |
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 {{=}}.
{noformat} user=> (apply = [(Long. -1) -1N (biginteger -1)]) true user=> (map hash [(Long. -1) -1N (biginteger -1)]) (0 0 -1) user=> {noformat} It is possible to have a PHM with two key/value pairs where the keys are equal, and the hash codes are different: {noformat} user=> (assoc clojure.lang.PersistentHashMap/EMPTY (biginteger -1) :oops! -1N :one) {-1N :one, -1 :oops!} {noformat} The expected behavior is the same as PersistentArrayMap, which does not have this issue, because it does not hash its keys: {noformat} user=> (assoc clojure.lang.PersistentArrayMap/EMPTY (biginteger -1) :oops! -1N :one) {-1 :one} {noformat} This same misbehavior also occurs for Doubles and Floats: {noformat} thalia.core=> (apply = [(Float. 1e9) (Double. 1e9)]) true thalia.core=> (map hash [(Float. 1e9) (Double. 1e9)]) (1315859240 1104006501) {noformat} That leads to the same difference in array-map and hash-map behavior as above for BigInteger and BigInt. |
Rich Hickey
made changes -
| Approval | Vetted [ 10003 ] | Not Approved [ 10008 ] |
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.