Reputation: 171
I know that Clojure switches from PersistentArrayMap
to PersistentHashMap
when a map is greater than 8 in size (8 key-value pairs). This can be verified by:
(type {0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8})
=> clojure.lang.PersistentHashMap
But if I create the above map using zipmap
:
(type (zipmap (range 9) (range 9)))
=> clojure.lang.PersistentArrayMap
I made sure that the construction is correct:
(= (zipmap (range 9) (range 9))
{0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8})
=> true
If I use (range 10)
, it starts using PersistentHashMap
. So for zipmap
, the size has to be 9 or greater before it starts using PersistentHashMap
.
I found this very weird. Why is there a difference in datastructure depending on whether I create a map manually or with zipmap
?
I'm using Clojure 1.8.
Upvotes: 1
Views: 168
Reputation: 171
This is because zipmap
creates the map incrementally using assoc
. Because of a bug, assoc
switches from ArrayMap
to HashMap
for size > 9, not for 9.
Look at this:
(type {0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7})
=> clojure.lang.PersistentArrayMap # size = 8
(type (assoc {0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7}
8 8))
=> clojure.lang.PersistentArrayMap # size = 9
(type (assoc {0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7}
8 8 9 9))
=> clojure.lang.PersistentHashMap # size = 10
The bug was fixed here: https://github.com/clojure/clojure/commit/ce9fbf61f113fdef1cbf8c1c0b4ea1a48831beef
Upvotes: 6