(ns maps.core) ;; In Clojure you can fetch items from a map three different ways. Which should ;; you use when? (= "bar" ({:foo "bar"} :foo)) ; map as function (= "bar" (:foo {:foo "bar"})) ; key as function (= "bar" (get {:foo "bar"} :foo)) ; `get` as function ;; ;; Incidentally, all three of these can take a default value to return if the ;; key is not present in the map. (= "not-here" ({:foo "bar"} :psych "not-here")) (= "not-here" (:psych {:foo "bar"} "not-here")) (= "not-here" (get {:foo "bar"} :psych "not-here")) ;; ;; Incidentally, using a default may not be what you want; you probably want to ;; use `or`: (not= "not-here" (:psych {:psych nil} "not-here")) (= "not-here" (or (:psych {:psych nil}) "not-here")) ;; ;; ;; There are two factors in choosing how to access items in a map: 1) the nature ;; of the map and/or key, and 2) the semantics of the map and key. ;; == NATURE OF THE MAP AND/OR KEY ;; Could the map be nil? You want to use either 'key as function' or '`get` as ;; function': (let [m nil] (m :foo)) ;; => NullPointerException ... ;; Could the key be anything other than a keyword? You want to use either 'map ;; as function' or '`get` as function': (let [k nil] (k {:foo "bar"})) ;; => NullPointerException ... (let [k "foo"] (k {:foo "bar"})) ;; => ClassCastException java.lang.String cannot be cast to clojure.lang.IFn ... ;; Could either the map or the key be nil? Could the key also be not-a-keyword? ;; Use '`get` as function'. ;; == SEMANTICS OF THE MAP AND KEY ;; Is the map a 'function'? For example, is it a transform: (let [m {"ping" "pong"}] (get m "ping")) ;; Realizing that it is a function and treating it semantically like a function ;; will help you later when you realize you want to do some more complicated ;; transform, or provide some default. In this case you should use 'map as ;; function': (let [ping->pong {"ping" "pong"}] (ping->pong "ping")) ;; Now you can make `ping->pong` into an arbitrary function. ;; Is the key a 'function'? For example, is it accessing data: (let [k :height-in-cm] (:height-in-cm {:height-in-cm 180.34})) ;; Realizing that accessing data and calculating data are equivalent (in a ;; purely functional sense) and treating the key as a function will help you ;; later. (let [height-in-cm (fn [m] (* 2.54 (:height-in-inches m)))] (height-in-cm {:height-in-inches 71})) ;; Now you can make `height-in-cm` into an arbitrary function. ;; This is function punning, and Clojure allows it in many ways. ;; == CONCLUSION ;; Which method of accessing a map you choose depends on whether the map and/or ;; key could be nil (in which case don't treat either as a function), and ;; whether semantically your code wants a function (in which case treat a map or ;; a keyword as a function, but make sure that your code could take an arbitrary ;; function just as easily).