Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clojure destructure map using :keys with qualified keywords not working

Tags:

clojure

I've tried this with both 1.7.0 and 1.8.0 and it appears that Clojure does not destructure maps using :keys whose keys are fully qualified. I don't think it has to do with being in the tail on the arguments as it doesn't work when I switch around the function argument positions as well.

(ns foo.sandbox)

(def foo ::foo)
(def bar ::bar)

(defn normalize-vals
  [mmap & [{:keys [foo bar] :as ops}]]
  (println "normalize-vals " ops " and foo " foo " bar" bar))

(normalize-vals {} {foo 1 bar 2})

=> normalize-vals  {:foo.sandbox/foo 1, :foo.sandbox/bar 2}  and foo  nil  bar  nil

However; this works:

    (defn normalize-vals
      [mmap & [{a foo b bar :as ops}]]
      (println "normalize-vals " ops " and foo " a " bar" b))

    (normalize-vals {} {foo 1 bar 2})

=> normalize-vals  {:cmt.sandbox/foo 1, :cmt.sandbox/bar 2}  and foo  1  bar  2

Is this a defect?

like image 771
Frank C. Avatar asked Mar 04 '26 14:03

Frank C.


1 Answers

You are destructuring using unqualified keywords, so instead of:

[mmap & [{:keys [foo bar] :as ops}]]

you should use

[mmap & [{:keys [::foo ::bar] :as ops}]]

You can use clojure.walk/macroexpand-all to expand normalize-vals:

(clojure.walk/macroexpand-all '(defn normalize-vals
                                 [mmap & [{:keys [foo bar] :as ops}]]
                                 (println "normalize-vals " ops " and foo " foo " bar" bar)))

=> (def normalize-vals (fn* ([mmap & p__26720] (let* [vec__26721 p__26720 map__26722 (clojure.core/nth vec__26721 0 nil) map__26722 (if (clojure.core/seq? map__26722) (. clojure.lang.PersistentHashMap create (clojure.core/seq map__26722)) map__26722) ops map__26722 foo (clojure.core/get map__26722 :foo) bar (clojure.core/get map__26722 :bar)] (println "normalize-vals " ops " and foo " foo " bar" bar)))))

The important part of the expansion to note is:

foo (clojure.core/get map__26722 :foo) 
bar (clojure.core/get map__26722 :bar)

The keys in the map destructuring are therefore converted to keywords at compile time and the values from the foo and bar vars in the namespace will not be used.

like image 178
Symfrog Avatar answered Mar 06 '26 22:03

Symfrog



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!