meander

All things about https://github.com/noprompt/meander Need help and no one responded? Feel free to ping @U5K8NTHEZ
micha 2020-02-13T03:10:45.201900Z

is there a nicer way to have an optional subpattern, like:

(m/or {:foo ?bar :baz ?baf} (m/let [?bar nil ?baf nil]))

micha 2020-02-13T03:11:35.202500Z

like m/? in glob lingo kind of

noprompt 2020-02-13T03:40:43.207100Z

Not really but I’m working toward having a thing like this on next branch of the project.

micha 2020-02-13T03:41:36.208700Z

cool thanks!

noprompt 2020-02-13T03:45:36.212300Z

Most of the time, this is fine. Actually, I think it’s nice that there’s no convenience for this because it has a tendency to encourage models that have more consistency. That’s just me though. OTOH I think defaults for unbound logic variables is useful and has a place.

micha 2020-02-13T03:46:18.213200Z

more consistency?

noprompt 2020-02-13T03:46:56.214Z

For maps though, we don’t check if the key has a value. We use get not find.

micha 2020-02-13T03:47:26.215Z

yep

micha 2020-02-13T03:48:02.216200Z

seems like a lot of times the structure you're maching against may be optimized for size

micha 2020-02-13T03:48:19.216700Z

so there will be optional parts

noprompt 2020-02-13T03:48:50.217900Z

By consistency I mean, a data model that doesn’t have a bunch of optionality. Some optionality is fine and it’s why map patterns work they way the do. But optionality implies logic putting more branches in the code if it’s not defaulted before moving it downstream.

noprompt 2020-02-13T03:51:53.220500Z

But I want the pattern matcher to be strict by default with the option to be less restrictive if you need.

noprompt 2020-02-13T03:52:25.221400Z

And I’m working toward that second part! 😄

micha 2020-02-13T03:53:04.222500Z

i was looking in &env for bindings

noprompt 2020-02-13T03:53:18.222900Z

I can put those in there.

micha 2020-02-13T03:53:26.223200Z

to use defsyntax to implement this

noprompt 2020-02-13T03:54:29.225200Z

But what you want is to use the parser to get the variables of the pattern passed in so that you can make the let hah or you can cheat and just look for them with tree seq or something! 😉

noprompt 2020-02-13T03:54:49.225700Z

(That’s more dangerous though.)

micha 2020-02-13T03:55:00.225900Z

haha yes, that would be the easy way for sure

micha 2020-02-13T03:55:50.226700Z

i see some examples, like subst parses the form

noprompt 2020-02-13T03:55:54.226900Z

All of this stuff will get better though in time.

noprompt 2020-02-13T03:57:06.228400Z

I can help more in a bit but it sounds like you’ll figure it out. 👍

micha 2020-02-13T03:57:24.228600Z

yeah so far pretty smooth!

noprompt 2020-02-13T04:07:48.229200Z

Fair warning: there’s a ton of code in there and mostly its because I was on new ground and exploring new techniques and ideas. The code on the zeta arm is being written mostly with epsilon and compiled to Clojure that uses the new zeta runtime. The quality of the implementation is much, much better.

micha 2020-02-13T04:09:26.229400Z

sounds great

micha 2020-02-13T04:30:46.229600Z

(defsyntax opt
  [pattern]
  (let [syms (atom [])]
    (->> (r.subst.syntax/parse pattern &env)
         (walk/prewalk #(let [t (:tag %) s (:symbol %)]
                          (when (and (map? %) (#{:lvr :mvr} t))
                            (swap! syms into [s (when (= t :mvr) [])]))
                          %)))
    `(e/or ~pattern (e/let [~@(deref syms)]))))

noprompt 2020-02-13T05:15:43.229800Z

@micha There are some utilities for pulling out variables like this.

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

(defsyntax opt
  [pattern]
  (let [syms (atom [])]
    (if (m/match-syntax? &env)
      (let [ast (m.match.syntax/parse pattern &env)
            lvars (m.syntax/logic-variables ast)
            binding-patterns (mapcat (juxt :symbol (constantly nil)) lvars)]
        `(m/or pattern (m/let [~@binding-pattersn])))
      &form)))

noprompt 2020-02-13T05:19:03.230100Z

You really only need to ask for logic variables because memory variables are always bound to [] even if they don’t match anything. This is why something like

[(or (pred odd? !odds) (pred even? !evens) ...]
works with no complaints from the compiler. Logic variables can’t be initialized like this.

micha 2020-02-13T05:19:42.230300Z

oh sweet