meander

agorgl 2026-02-16T14:13:18.444909Z

Am I misunderstanding the usage of m/or? I thought this should work:

(meander/match
    ;; input
    {:foo nil}

    ;; pattern
    {:foo (m/or nil {:bar ?bar})}

    ;; expression
    :aaa)
but it gives me non exhaustive pattern match while i expected to return :aaa

prnc 2026-02-16T15:38:36.113109Z

Not a meander expert at all, but I’ve used it in the past. I remember that there is a difference between plain ?x and memory variable !x, so the following works ca. as I would expect:

(m/match {:foo [1 2 3]}
  {:foo (m/or nil [!x ...])}
  !x)
;; => [1 2 3]
(m/match {:foo nil}
  {:foo (m/or nil [!x ...])}
  !x)
;; => []
On the other hand, your example throws. It seems that it expects to ‘see’ the same symbols bound in both (all) branches of m/or—you can ‘hack’ it like so (probably shouldn’t, this is just for demonstration):
(m/match {:foo nil}
  {:foo (m/or (m/let [?s nil] ?s) ?s)}
  {:val-of-s ?s})
But what is the underlying reason I don’t remember, if I ever I knew it at all ;P

prnc 2026-02-16T16:26:27.885779Z

apparently it is idiomatic to use (s/and ,,,) instead of how I used (m/let ,,,) above, see the “maybe” pattern: https://github.com/noprompt/meander/blob/epsilon/doc/cookbook.md#the-maybe-pattern,

agorgl 2026-02-16T17:36:08.241399Z

well, it seems that even the cookbook example doesn't work:

(meander/match
    ;; input
    {:foo nil}

    ;; pattern
    {:foo (m/or (m/and nil ?bar)
                {:bar ?bar})}

    ;; expression
    :aaa))

=> non exhaustive pattern match

prnc 2026-02-16T22:16:50.776119Z

this seems to work for me

prnc 2026-02-16T22:16:57.798619Z

;; meander/epsilon {:mvn/version "0.0.650"}

(require '[meander.epsilon :as m])

(m/match
  {:foo nil}

  {:foo (m/or (m/and nil ?bar)
          {:bar ?bar})}

  :aaa)
;; => :aaa

prnc 2026-02-18T12:14:55.264239Z

in your snippet you have meander/match but m/or instead it should be the following if you want to alias to meander

(require '[meander.epsilon :as meander])

(meander/match
  {:foo nil}

  {:foo (meander/or (meander/and nil ?bar)
          {:bar ?bar})}

  :aaa) 

agorgl 2026-02-18T12:16:32.764599Z

I do remember getting an error (or warning) when using meander/or inside the match macro, that didn't happen with m/or inside the macro

agorgl 2026-02-17T19:13:34.504589Z

Well, for some reason, requiring meander :as meander and doing meander/match instead of m/match messes up the result

agorgl 2026-02-17T19:13:39.902359Z

I really don't know why

agorgl 2026-02-19T10:35:54.224229Z

So it seems you are right. Here are some POCs for future searchers: not working:

clj -Sdeps '{:deps {meander/epsilon {:mvn/version "0.0.650"}}}' -e '(require '"'"'[meander.epsilon :as meander]) (meander/match {:foo nil} {:foo (m/or (m/and nil ?bar) {:bar ?bar})} :aaa)'
WARNING: Implicit use of clojure.main with options is deprecated, use -M -e (require '[meander.epsilon :as meander]) (meander/match {:foo nil} {:foo (m/or (m/and nil ?bar) {:bar ?bar})} :aaa)
Reflection warning, meander/util/epsilon.cljc:758:24 - reference to field val can't be resolved.
Execution error (ExceptionInfo) at user/eval6276 (REPL:1).
non exhaustive pattern match

Full report at:
/tmp/clojure-9301841438482740125.edn
working:
clj -Sdeps '{:deps {meander/epsilon {:mvn/version "0.0.650"}}}' -e '(require '"'"'[meander.epsilon :as meander]) (meander/match {:foo nil} {:foo (meander/or (meander/and nil ?bar) {:bar ?bar})} :aaa)'
WARNING: Implicit use of clojure.main with options is deprecated, use -M -e (require '[meander.epsilon :as meander]) (meander/match {:foo nil} {:foo (meander/or (meander/and nil ?bar) {:bar ?bar})} :aaa)
Reflection warning, meander/util/epsilon.cljc:758:24 - reference to field val can't be resolved.
:aaa

agorgl 2026-02-19T10:36:55.302799Z

In the second form a clj-kondo warning about unresolved var meander/or and meander/and pops up that is a bit misleading (that doesn't appear in the first form)