Maps & HashMaps
Sema provides two map types: sorted maps (BTreeMap-backed, deterministic ordering) and hashmaps (for O(1) performance-critical lookups).
Maps
Maps use curly-brace literal syntax with keyword keys:
{:name "Ada" :age 36} ; map literal
{:a 1 :b 2 :c 3} ; keywords as keysKeywords are callable — when used as a function, they look up their value in a map:
(:name {:name "Ada" :age 36}) ; => "Ada"hash-map
Create a map from key-value pairs.
(hash-map :a 1 :b 2) ; => {:a 1 :b 2}get
Look up a value by key. Works on both maps and hashmaps.
(get {:a 1 :b 2} :a) ; => 1
(get {:a 1 :b 2} :z) ; => nilassoc
Add or update a key-value pair, returning a new map.
(assoc {:a 1} :b 2) ; => {:a 1 :b 2}
(assoc {:a 1} :a 99) ; => {:a 99}dissoc
Remove a key, returning a new map. Works on both maps and hashmaps.
(dissoc {:a 1 :b 2} :a) ; => {:b 2}
(dissoc (hashmap/new :a 1 :b 2) :a) ; hashmap without :amerge
Merge multiple maps together. Later maps override earlier ones. Works on both maps and hashmaps — the result type matches the first argument.
(merge {:a 1} {:b 2} {:c 3}) ; => {:a 1 :b 2 :c 3}
(merge {:a 1} {:a 99}) ; => {:a 99}
(merge (hashmap/new :a 1) {:b 2}) ; hashmap with :a and :bkeys
Return the keys of a map as a list.
(keys {:a 1 :b 2}) ; => (:a :b)vals
Return the values of a map as a list.
(vals {:a 1 :b 2}) ; => (1 2)contains?
Test if a map contains a key.
(contains? {:a 1} :a) ; => #t
(contains? {:a 1} :b) ; => #fcount
Return the number of key-value pairs.
(count {:a 1 :b 2}) ; => 2map/entries
Return the entries as a list of key-value pairs.
(map/entries {:a 1 :b 2}) ; => ((:a 1) (:b 2))map/from-entries
Create a map from a list of key-value pairs.
(map/from-entries '((:a 1) (:b 2))) ; => {:a 1 :b 2}Higher-Order Map Operations
map/map-vals
Apply a function to every value in a map.
(map/map-vals (fn (v) (* v 2)) {:a 1 :b 2}) ; => {:a 2 :b 4}map/map-keys
Apply a function to every key in a map.
(map/map-keys
(fn (k) (string->keyword (string/upper (keyword->string k))))
{:a 1})
; => {:A 1}map/filter
Filter entries by a predicate that takes key and value.
(map/filter (fn (k v) (> v 1)) {:a 1 :b 2 :c 3}) ; => {:b 2 :c 3}map/select-keys
Select only the given keys from a map.
(map/select-keys {:a 1 :b 2 :c 3} '(:a :c)) ; => {:a 1 :c 3}map/update
Update a value at a key by applying a function.
(map/update {:a 1} :a (fn (v) (+ v 10))) ; => {:a 11}HashMaps
For performance-critical workloads with many keys, use hashmap for O(1) lookups instead of the sorted map.
hashmap/new
Create a new hashmap from key-value pairs.
(hashmap/new :a 1 :b 2 :c 3) ; create a hashmap
(hashmap/new) ; empty hashmaphashmap/get
Look up a value in a hashmap.
(hashmap/get (hashmap/new :a 1) :a) ; => 1hashmap/assoc
Add a key-value pair to a hashmap.
(hashmap/assoc (hashmap/new) :a 1) ; hashmap with :a 1hashmap/to-map
Convert a hashmap to a sorted map.
(hashmap/to-map (hashmap/new :b 2 :a 1)) ; => {:a 1 :b 2}hashmap/keys
Return the keys of a hashmap (unordered).
(hashmap/keys (hashmap/new :a 1 :b 2)) ; => (:a :b)hashmap/contains?
Test if a hashmap contains a key.
(hashmap/contains? (hashmap/new :a 1) :a) ; => #tGeneric Operations on HashMaps
The generic functions get, assoc, dissoc, keys, vals, merge, count, contains?, and all map/* higher-order operations also work on hashmaps, preserving the hashmap type:
(get (hashmap/new :a 1 :b 2) :a) ; => 1
(assoc (hashmap/new) :x 42) ; hashmap with :x 42
(dissoc (hashmap/new :a 1 :b 2) :a) ; hashmap without :a
(merge (hashmap/new :a 1) {:b 2}) ; hashmap with :a and :b
(count (hashmap/new :a 1 :b 2)) ; => 2
(map/map-vals (fn (v) (* v 2)) (hashmap/new :a 1)) ; hashmap with :a 2
(map/filter (fn (k v) (> v 1)) (hashmap/new :a 1 :b 2)) ; hashmap with :bmap/sort-keys
Sort a map by its keys. Converts hashmaps to sorted maps.
(map/sort-keys (hashmap/new :c 3 :a 1 :b 2)) ; => {:a 1 :b 2 :c 3}map/except
Remove specified keys from a map (inverse of map/select-keys).
(map/except {:a 1 :b 2 :c 3} '(:b)) ; => {:a 1 :c 3}
(map/except {:a 1 :b 2 :c 3} '(:a :c)) ; => {:b 2}map/zip
Create a map from a list of keys and a list of values.
(map/zip '(:a :b :c) '(1 2 3)) ; => {:a 1 :b 2 :c 3}Nested Map Operations
get-in
Access a value at a nested key path. Returns nil (or a default) if any key is missing.
(get-in {:a {:b {:c 42}}} [:a :b :c]) ; => 42
(get-in {:a {:b 1}} [:a :c]) ; => nil
(get-in {:a {:b 1}} [:a :c] "default") ; => "default"assoc-in
Set a value at a nested key path. Creates intermediate maps if they don't exist.
(assoc-in {:a {:b 1}} [:a :b] 42) ; => {:a {:b 42}}
(assoc-in {} [:a :b :c] 99) ; => {:a {:b {:c 99}}}update-in
Update a value at a nested key path by applying a function.
(update-in {:a {:b 10}} [:a :b] #(+ % 1)) ; => {:a {:b 11}}deep-merge
Recursively merge maps. Nested maps are merged rather than replaced. Non-map values in the overlay override the base.
(deep-merge {:a {:b 1 :c 2}} {:a {:b 99}}) ; => {:a {:b 99 :c 2}}
(deep-merge {:a {:b 1}} {:a 42}) ; => {:a 42}
(deep-merge {:a 1} {:b 2} {:c 3}) ; => {:a 1 :b 2 :c 3}