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

0 votes
in Java Interop by

When getting the value of a floated number in a map, the value isn't found if the map has more than 8 values.

For example:

(get {1.0 "a" 2.0 "b" 3.0 "c" 4.0 "d" 5.0 "e" 6.0 "f" 7.0 "g" 8.0 "h" 1 "i"} (float 1)) => nil
(get {1.0 "a" 2.0 "b" 3.0 "c" 4.0 "d" 5.0 "e" 6.0 "f" 7.0 "g" 8.0 "h"} (float 1)) => "a"

5 Answers

0 votes
by

Comment made by: ashercoren

The problem isn't only with maps.

Here is an example with a Set:
(contains? #{1.0 1.1} (float 1)) => true
(contains? #{1.0 1.1 1.2} (float 1)) => false

0 votes
by

Comment made by: jafingerhut

I believe that the fact that get lookup of a float in a map with at most 8 keys is an accident of the implementation.

The reason why it fails with larger maps and hash sets is that the hash value is different for (double 1.0) and (float 1.0).

user=> (hash (float 1.0)) 1065353216 user=> (hash 1.0) 1072693248

All of the values like 1.0 and others in your example default to type double. Note that if you force the keys of a map to be float, then lookup succeeds, even if the map has more than 8 keys:

user=> (get {(float 1.0) "a" 2.0 "b" 3.0 "c" 4.0 "d" 5.0 "e" 6.0 "f" 7.0 "g" 8.0 "h" 1 "i"} (float 1)) "a"

My guess is that except for the accident that get with a small map happens to return a successful lookup, everything here is working as designed.

I believe the reason that get with a small map does find a match for looking up (float 1) is probably because the implementation of small maps is as an ArrayMap, where lookup keys are sequentially compared against all keys in an array using clojure.core/= (or its Java equivalent), and:

user=> (= (float 1) (double 1)) true

0 votes
by

Comment made by: jafingerhut

Additional note: CLJ-1649 was created by someone hoping that floats and doubles should have hash and = consistent with each other. You can read more about it on that ticket's description. No judgment has been made whether such a change will ever be made in Clojure, but if one of Rich's comments on ticket CLJ-1036 is any indication, it seems unlikely to change.

General suggestion: Don't mix floats and doubles in Clojure code if you can possibly avoid it.

0 votes
by

Comment made by: ashercoren

Thank you @Andy!

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