meander

Werner 2025-10-21T17:15:06.546969Z

Hello. Newbie question, how can I get this to still match on the keys that do exist in my input and simply ignore the ones that doesn't exist?

(m/rewrite
    [{:name {:first "jon"
             :OOPS  {:family "doe"}}}]

    [{:name {:first !first
             :last {:family !last}}} ...]

    [{:my-name {:my-first !first
                :my-last  !last}} ...])
I'm expecting:
[{:my-name {:my-first "jon"}}]

or

[{:my-name {:my-first "jon", :my-last nil}}]
but instead the whole result is nil Thanks!

jgdavey 2025-10-21T18:06:09.432199Z

In your example, [{:name {:first !first :last {:family !last}}} ...] is the pattern, and so the whole map structure must be present to match

jgdavey 2025-10-21T18:08:37.148079Z

Let me play around a minute, I may be missing some context...

jgdavey 2025-10-21T18:11:57.658079Z

Yeah, because this is happening in a submap, that makes the :last key essentially required to match

jgdavey 2025-10-21T18:15:52.536559Z

There are several ways to deal with this, but perhaps the most straightforward (if obtuse) would be to add an additional clause:

(m/rewrite
 [{:name {:first "jon"
                :OOPS  {:family "doe"}}}]

 [{:name {:first !first
          :last {:family !last}}} ...]

 [{:my-name {:my-first !first
             :my-last  !last}} ...]

 [{:name {:first !first}} ...]

 [{:my-name {:my-first !first
             :my-last  nil}} ...])

jgdavey 2025-10-21T18:23:24.760099Z

But you can also use recursion to break the pattern down into the sequence and map parts:

(m/rewrite
 [{:name {:first "jon"
          :last  {}}}
  {:foo "x"}]

 {:name {:first ?first
         :last {:family ?last}}}
 {:my-name
  {:my-first ?first
   :my-last ?last}}

 {:name {:first ?first}}
 {:my-name
  {:my-first ?first
   :my-last nil}}

 [(m/cata !maps) ...]
 [!maps ...])

jgdavey 2025-10-21T18:26:34.781729Z

Finally, you can condense the 2 clauses into 1 by explicitly making the optional :last key nilable:

(m/rewrite
 [{:name {:first "jon"
          :OOPS  {}}}]

 {:name {:first ?first
         :last (m/or {:family ?last}
                     (m/and nil ?last))}}
 {:my-name
  {:my-first ?first
   :my-last ?last}}

 [(m/cata !maps) ...]
 [!maps ...])

Werner 2025-10-21T19:04:39.730049Z

Thank you for providing some options, I'll play around with it tomorrow. 🙏🏻

Werner 2025-10-22T15:40:52.289479Z

Works great!