Skip to main content

Better handling of namespaced keywords in maps with Clojure 1.9

Clojure 1.9 (or rather the alphas as of writing this) add some nice shortcuts to deal with maps containing namespaced keywords.

First of all there is now a reader macro #:ns{} to put the namespace on all keys in that map:

user=> (def customer #:customer{:id 42 :name "Acme"})
#'user/customer
user=> customer ; even prints as such
#:customer{:id 42, :name "Acme"}
user=> (assoc customer :something/else 23) ; once you mix, you get the regular output
{:customer/id 42, :customer/name "Acme", :something/else 23}
user=> (:customer/id customer) ; get works as expected
42
user=> #::{:id 23} ; also :: works as expected
#:user{:id 23}

The destructuring side of things got some enhancements too. The :keys destructuring not can also be used with a namespace:

user=> (let [{:customer/keys [id name]} customer] [id name])
[42 "Acme"]
user=> (def order #:order{:id 42
                          :customer customer
                          :items [#:order-item{:id 23
                                               :name "WiFi wire"
                                               :amount 2
                                               :price 64.0}]})
#'user/order
user=> (let [{{:customer/keys [id name]} :order/customer, :order/keys [items]} order]
         [id name (transduce (map (fn [{:order-item/keys [amount price]}] (* amount price))) + 0 items)])
[42 "Acme" 128.0]