Say I have a clojure map that uses keywords as its keys:
(def my-car {:color \"candy-apple red\" :horsepower 450})
I know that I can look u
I put together a list of arguments for and against the two forms. (Edit: Added third option - (get map :key) which is my new favorite despite being a little bit more verbose)
1) Requested in coding standards
http://dev.clojure.org/display/community/Library+Coding+Standards
2) Still works when map is nil
> (:a nil)
nil
> (nil :a)
ERROR: can't call nil
---counterargument--- if key may be nil, other forms are better
> ({:a "b"} nil)
nil
> (nil {:a "b"})
ERROR: can't call nil
3) Works better for threading and mapping over collections of objects
(-> my-map
:alpha
fn-on-alpha
:beta
fn-on-beta
:gamma
> (def map-collection '({:key "values"} {:key "in"} {:key "collection"}))
> (map :key map-collection)
("values" "in" "collection")
---counterargument--- the code structure of threading is different than usual so different idiomatic tendencies could be applied for map access when needed
4) Potential optimization benefit? (needs verification)
1) Does not throw error when key is non-keyword or nil
> ({:a "b"} nil)
nil
> (nil {:a "b"})
ERROR: can't call nil
> ({"a" "b"} "a")
"b"
> ("a" {"a" "b"})
ERROR: string cannot be cast to IFn
2) Consistency with list access in Clojure
> ([:a :b :c] 1)
:b
> (1 [:a :b :c])
ERROR: long cannot be cast to IFn
3) Similarity to other forms of object access
java> my_obj .alpha .beta .gamma .delta
clj > ((((my-map :alpha) :beta) :gamma) :delta)
clj > (get-in my-map [:alpha :beta :gamma :delta])
cljs> (aget js-obj "alpha" "beta" "gamma" "delta")
4) Alignment when accessesing multiple keys from the same map (separate lines)
> (my-func
(my-map :un)
(my-map :deux)
(my-map :trois)
(my-map :quatre)
(my-map :cinq))
> (my-func
(:un my-map)
(:deux my-map)
(:trois my-map)
(:quatre my-map)
(:cinq my-map))
---counterargument--- alignment worse when accessing same key from multiple maps
> (my-func
(:key map-un)
(:key map-deux)
(:key map-trois)
(:key map-quatre)
(:key map-cinq)
> (my-func
(map-un :key)
(map-deux :key)
(map-trois :key)
(map-quatre :key)
(map-cinq :key)
1) NEVER causes error if arg1 is map/vector/nil and arg2 is key/index/nil
> (get nil :a)
nil
> (get nil nil)
nil
> (get {:a "b"} nil)
nil
> (get {:a "b"} :q)
nil
> (get [:a :b :c] nil)
nil
> (get [:a :b :c] 5)
nil
2) Consistency in form with other Clojure functions
> (get {:a "b"} :a)
:b
> (contains? {:a "b"} :a)
true
> (nth [:a :b :c] 1)
:b
> (conj [:a :b] :c)
[:a :b :c]
3) Alignment benefits of map-first
> (my-func
(get my-map :un)
(get my-map :deux)
(get my-map :trois)
(get my-map :quatre)
(get my-map :cinq))
4) Get-in can be used for nested access with a single call
> (get-in my-map [:alpha :beta :gamma :delta])
> (aget js-obj "alpha" "beta" "gamma" "delta")
Source: testing on http://tryclj.com/