Nested map updates in Clojure
Reads and rewrites a two-level tool inventory through key paths instead of hand-nested calls.
;; get-in walks a path of keys through nested maps and returns a
;; default when the path runs out early.
(def inventory
{:tools {:hammer {:on-hand 4 :bin "A1"}
:chisel {:on-hand 0 :bin "A3"}}})
(println (format "hammers %d" (get-in inventory [:tools :hammer :on-hand])))
(println (format "bolts %d" (get-in inventory [:parts :bolt :on-hand] 0)))
;; assoc-in writes a value at a path, building maps along the way.
;; update-in instead applies a function to whatever sits there, with
;; any extra arguments passed after the current value.
(def stocked (assoc-in inventory [:tools :chisel :on-hand] 6))
(def sold (update-in stocked [:tools :hammer :on-hand] - 3))
(def moved (update-in sold [:tools :chisel :bin] str "-back"))
(println (format "hammers now %d, chisel bin %s"
(get-in sold [:tools :hammer :on-hand])
(get-in moved [:tools :chisel :bin])))
How it works
(get-in inventory [:tools :hammer :on-hand])walks a path of keys, and the trailing0in the bolts lookup is the default when the path is missing.(assoc-in inventory [:tools :chisel :on-hand] 6)writes a value at the path and returns a new map.(update-in stocked [:tools :hammer :on-hand] - 3)applies-to the count already there, passing3as an extra argument.
Keywords and builtins used here
defformatprintlnstr
The run, in numbers
- Lines
- 19
- Characters to type
- 855
- Tokens
- 130
- Three-star pace
- 65 tpm
At the three-star pace of 65 tokens a minute, this run takes about 120 seconds.
Step 2 of 3 in State & records, step 23 of 27 in Language basics.