meander

agorgl 2026-02-13T14:38:24.622369Z

Hello! I'm using meander/match for basic data mapping between dto and domain objects. How can I ignore input map fields that have nil value without doing post processing? For now meander matches on these fields and I get keys with nil values on my output map (expected)

prnc 2026-02-16T15:43:31.466439Z

@agorglouk again not an expert, but it is worth remembering that the expr argument to m/match is ‘just’ a clojure expressions (AFAIU), so:

(m/match
  {:foo 123 :bar nil}

  {:foo ?foo
   :bar ?bar}

  (cond-> {:foo ?foo}
    ?bar (assoc :bar ?bar)))
you can just check what has been bound to ?bar and decide what to do with it on the expr side, so to speak

agorgl 2026-02-16T17:32:34.556809Z

That's what I'm doing so far! I was hoping that there is a better, a bit more declarative way to declare this kind of thing near the pattern as this would communicate better the intent

lwhorton 2026-02-13T17:15:17.651409Z

im pretty sure this is :kw (m/not (m/some _))

agorgl 2026-02-13T17:53:43.747749Z

vanilla poc:

(meander/match
    {:foo 123 :bar nil}

    {:foo ?foo
     :bar ?bar}

    {:otherfoo ?foo
     :otherbar ?bar})

=> {:otherfoo 123, :otherbar nil}
try with (m/not (m/some)):
(meander/match
    {:foo 123 :bar nil}

    {:foo ?foo
     :bar (m/not (m/some ?bar))}

    {:otherfoo ?foo
     :otherbar ?bar})

=> Execution error (ExceptionInfo) at ...
non exhaustive pattern match
so this doesn't seem to work

agorgl 2026-02-13T18:00:15.033939Z

(edited poc above)

lwhorton 2026-02-13T18:07:48.864959Z

wouldn't you want something like: {:foo ?foo :bar (m/not (m/some _))} {:otherfoo ?foo}? this says "if we find foo and bar is nil, remap foo to :otherfoo".

lwhorton 2026-02-13T18:09:02.543669Z

meander might not be what you are looking for. or, at least my knowledge of m/find m/search and m/cata isn't good enough to build the expression. if any key's value can be nil and you wish to exclude all k-v pairs whose k is nil... that is a combinatorial explosion of matches.

agorgl 2026-02-13T18:09:03.483229Z

What I want is, foo maps to otherfoo, and if bar not nil, map to otherbar else skip otherbar key from output

agorgl 2026-02-13T18:10:38.605219Z

I want this rule to be specific for bar

lwhorton 2026-02-13T18:12:17.517449Z

if you want to target a specific key, provide two matcher patterns in the appropriate order.

lwhorton 2026-02-13T18:12:54.420919Z

try to match foo and bar where bar is not nil, then try to match foo and bar where bar is nil. in one case return a map with otherfoo, otherbar. in the other case, only return otherbar.

lwhorton 2026-02-13T18:14:02.353609Z

this doesn't scale well, but can be useful for very small sets of matches. there is probably a better way to do it with the more complicated search/scan/or/cata/rewrite ... but as you've probably noticed, the exception-infos aren't super helpful and the docs are a bit light.

lwhorton 2026-02-13T18:15:02.825419Z

personally, i would do a postprocess step and not try to write a complicated meander expression. something like remove-nil-pairs is trivial to write. you might be able to construct something that does it 'natively' via meander ... but i've found it very hard to do anything but the most basic match-and-rewrite because or, and, scan, search, cata, rewrite gets difficult. i love meander for transforms/reshaping. but i quickly abort using it (or use a post processing step) for anything beyond the most basic m/match.

agorgl 2026-02-13T18:15:20.807879Z

Yeah I suppose I need to re-read the docs and try to get a better grasp of it as a whole. We'll see where this leads :)

lwhorton 2026-02-13T18:15:59.115319Z

do let me know if you come up with some great insight. i feel badly because the library is probably awesome, but i haven't been able to crack through the docs and the implementation is hard for me to grok. that said, the most common/basic usage is a huge win imo. the matcher works great as a data-driven, less strict schema/spec/malli.

agorgl 2026-02-13T18:16:22.710369Z

Will do, thanks for giving it a try!

cch1 2026-02-15T22:53:33.429989Z

IIUC, this is pretty simple:

(m/match {:foo 123 :bar nil}
         {:foo ?foo :bar nil} {:otherfoo ?foo}
         {:foo ?foo :bar ?bar} {:otherfoo ?foo :otherbar ?bar})
=> {:otherfoo 123}