array-map

added
1.0

ns
clojure.core

type
function

(array-map) (array-map & keyvals)

Constructs an array-map. If any keys are equal, they are handled as
if by repeated uses of assoc.

                user=> (array-map [1 2] [3 4 5])
{[1 2] [3 4 5]}
            
                user=> (array-map :a 10)
{:a 10}

user=> (array-map :a 10 :b 20)
{:a 10 :b 20}

user=> (apply array-map [:a 10 :b 20 :c 30])
{:a 10 :b 20 :c 30}

user=> (apply assoc {} [:a 10 :b 20 :c 30]) ;same result using assoc
{:a 10 :b 20 :c 30}

            
                user=> (keys (assoc (array-map :foo 10 :bar 20) :baz 30))
(:baz :foo :bar)
; baz is first; :foo and :bar follow the order given to array-map


;; My results have consistently been different from what's listed above.
user=> (keys (assoc (array-map :foo 10 :bar 20) :baz 30))
; => (:foo :bar :baz)
user=> (assoc (array-map :foo 10 :bar 20) :baz 30)
; => {:foo 10, :bar 20, :baz 30}
user=> *clojure-version*
; => {:major 1, :minor 8, :incremental 0, :qualifier nil}
;; As long as I have an array map, new items get added to the end, not
;; the beginning.
            
                ;; Sometimes Clojure will automatically choose between a hash map and
;; an array map.  What's the rule?  Let's try a few experiments.

;; Start with a quick way to make a map with N items.
user=> (defn make-map [count] (zipmap (range count) (range count)))
;; => #'user/make-map
user=> (make-map 3)
;; => {0 0, 1 1, 2 2}

;; Try a few maps.  The cutoff seems to be 9.5.  If you have fewer than
;; 9.5 items you get an array map.  If you have more than 9.5 items you
;; get a hash map.
user=> (type (make-map 8))
;; => clojure.lang.PersistentArrayMap
user=> (type (make-map 9))
;; => clojure.lang.PersistentArrayMap
user=> (type (make-map 10))
;; => clojure.lang.PersistentHashMap
user=> (type (make-map 11))
;; => clojure.lang.PersistentHashMap

;; Using assoc we get similar results.  9 or fewer items yields an array
;; map.  10 or more yields a hash map.
user=> (type (assoc (make-map 9) :x 1))  ; 10 items -> hash map.
;; => clojure.lang.PersistentHashMap
user=> (type (assoc (make-map 8) :x 1))  ; 9 items -> array map.
;; => clojure.lang.PersistentArrayMap
user=> (type (assoc (make-map 8) :x 1 :y 2))  ; 10 items -> hash map.
;; => clojure.lang.PersistentHashMap
user=> (type (assoc (assoc (make-map 8) :x 1) :y 2))  ; 10 items -> hash map.
;; => clojure.lang.PersistentHashMap

;; But when we use { and } to create a map, the cutoff seems to move to 8.5.
;; A map with 9 items created with assoc or zipmap would be an array map,
;; but a map with 9 items created by { } is a hash map.
user=> (type {0 0, 1 1, 2 2, 3 3, 4 4, 5 5, 6 6, 7 7})  ; 8 items -> array map.
;; => clojure.lang.PersistentArrayMap
user=> (type {0 0, 1 1, 2 2, 3 3, 4 4, 5 5, 6 6, 7 7, 8 8})  ; 9 items -> hash
;; => clojure.lang.PersistentHashMap

;; Calling dissoc on an array map always yields an array map, regardless of
;; the size of the map.
;; Let's start by making a large array map then remove a few items.  This will
;; give us array maps larger than you could create with assoc.
user=> (def array20 (apply array-map (range 40)))
;; => #'user/array20
user=> (type array20)
;; => clojure.lang.PersistentArrayMap
user=> (type (dissoc array20 6))
;; => clojure.lang.PersistentArrayMap
user=> (count (dissoc array20 6))
;; => 19
user=> (type (dissoc array20 6 2))
;; => clojure.lang.PersistentArrayMap
user=> (count (dissoc array20 6 2))
;; => 18

;; Calling dissoc on a hash map always yields another hash map, regardless
;; of the size of the map.
;; Let's start by making a large hash map then remove a lot of items.  This
;; will give us hash maps smaller than you could create with assoc.
user=> (type (make-map 40))
;; => clojure.lang.PersistentHashMap
user=> (type (apply dissoc (make-map 40) (range 1 80)))
;; => clojure.lang.PersistentHashMap
user=> (count (apply dissoc (make-map 40) (range 1 80)))
;; => 1
user=> (apply dissoc (make-map 40) (range 1 80))
;; => {0 0}
user=> (type (apply dissoc (make-map 40) (range 0 80)))
;; => clojure.lang.PersistentHashMap
user=> (count (apply dissoc (make-map 40) (range 0 80)))
;; => 0
user=> (apply dissoc (make-map 40) (range 0 80))
;; => {}