Last Updated: May 04, 2019
·
612
· niclasmeier

Getting values from maps

There are several ways to get stuff from a map. Some of them are a good idea, some of them have their pitfalls:

The Classic:

(get user :first-name)
(get-in user [:address :street])

The get function is the standard function to get stuff of a map. Works for all datatypes and works also fine with things like java.util.HashMap or records. The only drawback is, that it is quite clumsy to read/write.
For nested maps use the get-in function, It works similar to the get function and works well even for different key types (e.g. :address "street")

Looks like beans:

(user :first-name)
((user :address) :street)

A map in Clojure is also of function and you may use it to access values from it. Pros: Works with all datatypes and looks - e.g. for old Java guys like me - like using bean properties. Cons: Works only on Clojure maps and not on things like HashMap or records. Throws a NullPointerException when the map is nil, therefore nested maps are quite ugly to handle.

Using this is definitely not a good idea - but to be honest some of my early Clojure code is crowded with this stuff.

Less code

(:first-name user)
(:first-name user "John")

(:street (:address user))
(-> user :address :street)

This is for the people who want to type less. It has also good readability (from my point of view) and works well - e.g. like get - for HashMap or records and you also my supply a default value. There are two things to consider: a) It only works for keywords and b) it is somewhat slower for HashMap.
For nested maps this changes a bit. The simple nested forms lacks some readability because you have to reverse the order of keys but with the threading macro you can simply avoid this. Another nice to know is, that it's 20-30% faster than the get-in function (if this is really mattering to you).