Frank C.
Frank C.

Reputation: 8088

Destructuring map of map with unknown keys

I have the following as an example:

(def _t2 {:oxnard {:value-type "string" :rec-name "foo"}})

where :oxnard is dynamic and unknown a-priori to function and the contained map is made up of well-known key names (e.g. :value-type and :rec-name).

I'm trying to write a function with destructuring without knowing the outer map keyword, for example:

(defn if-foo? [ignoremapfirstkey & 
  {:keys [value-type rec-name]}] 
  (= rec-name "foo"))

or similar; however, I can't seem to get around the outer key name not-being known.

Upvotes: 3

Views: 760

Answers (2)

Michał Marczyk
Michał Marczyk

Reputation: 84331

Assuming that your function is passed the dynamic key as an argument, you can use it to extract the inner map, which can then use it to extract the inner map and destructure that:

(let [{:keys [foo bar]} (get outer-map :inner-key)]
  ...)

;; k could be a function argument or Var rather than a let local
(let [k :inner-key
      {k {:keys [foo bar]}} outer-map]
  ...)

And if the point was that there will always be precisely one entry in the outer map, you can use first and val to extract the inner map or call seq on the map and destructure that:

(let [{:keys [foo bar]} (val (first outer-map))]
  ...)

(let [[[_ {:keys [foo bar]}]] (seq outer-map)]
  ...)

In the latter case, (seq outer-map) will have the form ([k v]) (a seq containing one map entry); the outer vector in the destructuring form destructures the seq, the inner vector destructures the map entry, _ is a placeholder for the key that you don't care about and {:keys [foo bar]} destructures the inner map. You do have to call seq on the map yourself, the destructuring machinery won't do it for you.

Upvotes: 5

Mars
Mars

Reputation: 8854

What about this?

(defmacro somekey
  [complex-map]
  (let [k (first (keys complex-map))]    ; get key from the outer map
    `(let [{inner-map# ~k} ~complex-map] ; use it for destructuring
        inner-map#)))                    ; make this as complex as you want

Maybe there's a flaw here and I'm risking downvotes, but it seems to work. Might not be better than Michal's answer for practical use, even so. (And of course, other things being equal, it's better to avoid macros unless they're really necessary.)

Upvotes: 0

Related Questions