Update (Aug 8, 2017): I found another solution, outlined here! Not necessarily exciting, but another way, nonetheless!

I came across a scenario where I needed to add a nested clojure map into an existing map; something like:

Original:

  {:movie {:info {:name "Little Trouble in Big Manhattan"
                  :year "2020"
                  :format "BR-1000"}}}

Suppose I wanted to add an actor, and a language for the film? So in the end, I’d like something like this:

Desired:

  {:movie {:info {:name "Little Trouble in Big Manhattan"
                  :year "2020"
                  :format "BR-1000"
                  :actor "JeSuis VonBraun"
                  :language "French"}}}

Here’s my solution:

  • First, define the original map to make it easier:
(def movie {:movie {:info {:name "Little Trouble in Big Manhattan"
                           :year "2020"
                           :format "BR-1000"}}})
=> #'ns-movies-db/movie
  • Insert :actor:
(assoc-in movie [:movie :info :actor] "JeSuis VonBraun")
=> {:movie {:info {:name "Little Trouble in Big Manhattan",
                   :year "2020",
                   :format "BR-1000",
                   :actor "JeSuis VonBraun"}}}
  • Similarly, :language can be added in the same way:
(assoc-in movie [:movie :info :language] "French")
=> {:movie {:info {:name "Little Trouble in Big Manhattan",
                   :year "2020",
                   :format "BR-1000",
                   :language "French"}}}

But what if I want to add both? My current strategy is to wrap one assoc-in inside of another, using the result of the inner as the map for the outer:

(assoc-in (assoc-in movie [:movie :info :actor] "JeSuis VonBraun")
          [:movie :info :language] "French")
=>{:movie {:info {:name "Little Trouble in Big Manhattan",
                  :year "2020",
                  :format "BR-1000",
                  :actor "JeSuis VonBraun",
                  :language "French"}}}

Voila!! I get the result I’m after! I’m must admit, however, that this does not feel like an elegant solution. I’ll keep digging to refactor this, and post a better solution once I find it!