Reputation: 426
So I'm used to having a nested array or map of settings in my applications. I tried setting one up in Clojure like this:
(def gridSettings
{:width 50
:height 50
:ground {:variations 25}
:water {:variations 25}
})
And I wondered if you know of a good way of retrieving a nested value? I tried writing
(:variations (:ground gridSettings))
Which works, but it's backwords and rather cumbersome, especially if I add a few levels.
Upvotes: 23
Views: 14012
Reputation: 5410
Maps are partial functions (as in not total). Thus, one can simply apply them as functions. Based on the map from the question:
(gridSettings :ground)
;=> {:variations 25}
The result is a map. So, it can be applied again, which results in a very similar (but not backwards) "syntax" as proposed in the question:
((gridSettings :ground) :variations)
;=>25
Upvotes: 3
Reputation: 33637
Apart from what other answers has mentioned (get-in
and ->
macro), sometimes you want to fetch multiple values from a map (nested or not), in those cases de-structuring can be really helpful
(let [{{gv :variations} :ground
{wv :variations} :water} gridSettings]
[gv wv])
Upvotes: 14
Reputation: 61011
You can use the thread-first macro:
(-> gridSettings :ground :variations)
I prefer ->
over get-in
except for two special cases:
Upvotes: 31
Reputation: 8850
That's what get-in
does:
(get-in gridSettings [:ground :variations])
From the docstring:
clojure.core/get-in ([m ks] [m ks not-found]) Returns the value in a nested associative structure, where ks is a sequence of keys. Returns nil if the key is not present, or the not-found value if supplied.
Upvotes: 40