简体   繁体   中英

clojure - trouble destructing map inside macro

I'm a newbie in clojure, so please bear with me.

Writing a macro as so:

 `(let [query#   (:query-params ~'+compojure-api-request+)
        options# (select-keys query# [:sort-by :from :to])])

First line of the let block destructures a query-params from http request - which produces this structure:

{sort-by billing-account/name, from 0, to 10, payment-due , payment-method , search }

And the trouble is with the second line - it returns an empty map when I use select-keys , however when I say for example (first query#) - the output looks like this: [sort-by billing-account/name]

Could anyone please explain why the select-keys does not work?

PS Tried (get query# :from) & (:from query#) - no luck there as well.

UPD

Keys were strings, not keywords - therefore using strings as keys works just fine.

By the way, you can also destructure string keys with :strs :

(let [m {"sort-by" "billing-account/name", 
         "from" "0",
         "to" "10", 
         "payment-due" nil, 
         "payment-method", "search"}
      {:strs [sort-by from to payment-due payment-method]} m]
  (println sort-by from to payment-due payment-method))

;;=> billing-account/name 0 10 nil search     

See https://clojure.org/guides/destructuring for a full description of the destructuring syntax.

I think you are confused by the differences between keywords, symbols and strings. In your comment you say that they're symbols, but in your edit you say they're strings.

You should read up on the difference:

The idiomatic thing is to usually prefer using keywords as map keys, although stuff that comes from the internet (json, http headers, etc) is sometimes all strings.

To answer your question directly, the keys passed to select-keys need to be equal (using the = function) to the ones in the map, so in this case they need to be the same type.

;; For example

(select-keys {'foo 1 'bar 2} ['foo]) ;=> {foo 1}

(select-keys {:foo 1 :bar 2} [:foo]) ;=> {:foo 1}

(select-keys {"foo" 1 "bar" 2} ["foo"]) ;=> {"foo" 1}

Also I question the need for this to be a macro, is there a reason that a plain function won't work?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM