Fork me on GitHub
#meander
<
2020-07-08
>
ikrimael00:07:47

I marked questions/requests for feedback with QUESTION tag inline

noprompt00:07:43

I saw that. 🙂

noprompt00:07:00

This is great by the way. 👍

ikrimael00:07:30

meta-question: ofc lmk if there's other changes to make it easier to review. I had a bunch of examples and scrapped them once I realized I could answer all of them by looking at the tests file

ikrimael00:07:58

ofc, i'll be going back to add them; was just way off in that first attempt

noprompt00:07:38

Ha! It’s funny because I’ve often thought it might be more accessible/friendly to extract some of the test examples into the cookbook i.e. the fib-test stuff.

ikrimael00:07:11

heh, fwiw, they were super helpful! also made me realize the docs didn't include the full api

noprompt00:07:03

Yeah, there’s a lot there and I generally don’t follow implementation updates, etc. with doc updates (I should, I know).

ikrimael01:07:06

meta-comment: i think also helpful is more philosophical comment/feedback of "should meander even be used for this scenario?"

noprompt01:07:17

Definitely. Honestly, we have made a good faith effort to do that here.

ikrimael01:07:18

I often find myself looking at my meander rewrite and thinking I've made it more obtuse. (Ofc as one who's learning both clojure + meander, I put weight = near 0 on my thoughts at this point)

noprompt01:07:40

A meander group-by often comes up and the recommendation has always been to just use group-by.

ikrimael01:07:28

ah interesting; i'll have to look that up

ikrimael01:07:36

i've also opted to put the different iterations of my meander attempts in the cookbook (both for future me's sake and learning value); ofc feel free to scrub them or maybe move them to a tutorial

noprompt01:07:09

Jimmy does that to great effect in some of his posts and I think it’s a nice way to guide someone from one place to the next.

noprompt01:07:51

With rewrite you can do the (m/app #(->OppathSeg :seg-attr %1) !seg) on the right side.

noprompt01:07:48

Someone I work with isn’t really a fan of m/app on the left side.

noprompt01:07:53

If I can defer m/app to the right side, I do.

ikrimael01:07:32

i'd say i'm in that camp too; i couldn't figure out how to carry the "patteern match state" though to the right side

ikrimael01:07:16

i.e. I find myself wanting to do this alot

token ::= (:arg-in|:arg-out) ?argname
    pseudocode-result:: (str (emit-in ?arg-attr)|emit-out :arg-attr) ?argname)

noprompt01:07:51

Strings are on the list of things match/build.

noprompt01:07:44

I’ve been catching up on some research and experimenting with how to model, compile, interpret, etc.

ikrimael01:07:24

sans strings, would it be possible to do that? I keep reaching basically for the rhs to apply different functions based on the pattern matched

noprompt01:07:24

Another thing that’s on the list is a way to aggregate.

noprompt01:07:44

Possible to pattern match on strings?

ikrimael01:07:17

ah, i mean excluding the string case

noprompt01:07:01

Oh are you asking if the thing matches bind it to a variable?

ikrimael01:07:31

ie in my example, i pattern match an xpath segment (ignore that it's a string). I want to apply a transform to said xpath segment depending on the type of xpath segment

noprompt01:07:09

Use two memory variables?

noprompt01:07:44

!seg-attrs , !seg-chlds and then apply the transforms on the right.

ikrimael01:07:46

oh; can I use m/or on the rhs in substitutions?

noprompt01:07:19

You can’t use m/or on the right side yet.

noprompt01:07:32

But memory variables are always initialized to the empty vector at a minimum.

noprompt01:07:18

[(m/app f !seg-attrs) ... (m/app g !seg-chlds) ...]

noprompt01:07:54

FYI I gotta step away for a bit. Should be back in a couple hours.

ikrimael01:07:05

sure, np! let me play with that a little

ikrimael01:07:19

ah couldn't get it to work still. Here's a simplified snippet showcasing actual vs desired output

(defn f [xseg] {:kind :seg-attr :val xseg})
(defn g [xseg] {:kind :seg-chld :val xseg})
(m/rewrite ["oppas" "obj1" "@attr1" "@attr2" "obj2"]
  (m/with [%segattr (m/pred #(= (first %1) \@)    !seg-attrs)
           %segobj  (m/pred #(not= (first %1) \@) !seg-chlds)]
          [(m/re #"obj|oppas|dc" ?ns) . (m/or %segobj %segattr) ...])
  {:ns    (keyword ?ns)
   :xsegs [(m/app f !seg-attrs) ... (m/app g !seg-chlds) ...]}
)
;; INCORRECT: => 
{:ns (keyword "oppas")
 :xsegs
 [{:kind :seg-attr, :val "@attr1"}
  {:kind :seg-attr, :val "@attr2"}
  {:kind :seg-chld, :val "obj1"}
  {:kind :seg-chld, :val "obj2"}]}

;; CORRECT =>
{:ns (keyword "oppas")
 :xsegs
 [{:kind :seg-chld, :val "obj1"}
  {:kind :seg-attr, :val "@attr1"}
  {:kind :seg-attr, :val "@attr2"}
  {:kind :seg-chld, :val "obj2"}]}

noprompt03:07:23

Gotcha. There are two approaches you could apply here. The first one uses a helper to construct the xseg:

(defn make-xseg [val]
  (m/rewrite val
    (m/re #"@.*" ?val)
    {:kind :seg-attr :val ?val}

    (m/re #"[^@].*" ?val)
    {:kind :seg-chld :val ?val}

    ?val
    {:kind :unknown :val ?val}))


(m/rewrite ["oppas" "obj1" "@attr1" "@attr2" "obj2"]
  [(m/re #"obj|oppas|dc" ?ns) . !segs ...]
  {:ns (m/keyword ?ns)
   :xsegs [(m/app make-xseg !segs) ...]})
;; =>
{:ns :oppas,
 :xsegs
 [{:kind :seg-chld, :val "obj1"}
  {:kind :seg-attr, :val "@attr1"}
  {:kind :seg-attr, :val "@attr2"}
  {:kind :seg-chld, :val "obj2"}]}
The second uses m/cata on the left or right side:
;; Left side
(m/rewrite ["oppas" "obj1" "@attr1" "@attr2" "obj2"]
  [(m/re #"obj|oppas|dc" ?ns) . (m/cata !segs) ...]
  {:ns (m/keyword ?ns)
   :xsegs [!segs ...]}

  (m/re #"@.*" ?val)
  {:kind :seg-attr :val ?val}

  (m/re #"[^@].*" ?val)
  {:kind :seg-chld :val ?val}

  ?val
  {:kind :unknown :val ?val})

;; Right side
(m/rewrite ["oppas" "obj1" "@attr1" "@attr2" "obj2"]
  [(m/re #"obj|oppas|dc" ?ns) . !segs ...]
  {:ns (m/keyword ?ns)
   :xsegs [(m/cata !segs) ...]}

  (m/re #"@.*" ?val)
  {:kind :seg-attr :val ?val}

  (m/re #"[^@].*" ?val)
  {:kind :seg-chld :val ?val}

  ?val
  {:kind :unknown :val ?val})

👌 3
markaddleman04:07:21

I hadn't thought about using cata on the right side before. In this example, it doesn't look like there's much advantage. Offhand, can you think of a situation where cata on the rhs is meaningfully different/important?

JAtkins04:07:59

@e749 Thank you for adding more examples! I have tried a couple times to pick up meander, always got stuck on something. Hoping to make a push in 2-3 weeks to start using it alot more. (should go without saying thanks to Jole and the other authors too though 🙂)

ikrimael04:07:24

sure np! feel free to add feedback to the draft PRs

noprompt04:07:03

@U5P29DSUS Reach out when you get stuck. If I can help, I will. 🙂

JAtkins04:07:04

Thanks, I will probably end up doing so 🙂. I'm trying to set myself up for success in https://github.com/JJ-Atkinson/Fisher project, and I think meander might be quite helpful for sections.

ikrimael04:07:25

@U5P29DSUS hah! exactly what i'm using it (albeit targetted towards C/C++)

ikrimael05:07:16

parse decorated c/c++ => highlevel IR => clojure does term rewriting/inline expansion/etc => codegen c/c++ & UI bindings => JIT back into the app/editor

💯 3
ikrimael05:07:07

it's more or less the lighttable dream but with c/c++ target & gamedev focus

JAtkins05:07:06

Gacha. Sounds neat. It is/was a great piece of software.

noprompt04:07:53

@markaddleman Cata on the right side can be used to construct a value to be recursively rewritten. It’s the dual of the left.

markaddleman04:07:36

Ah, of course. Thanks

noprompt04:07:32

(m/rewrite ["oppas" "obj1" "@attr1" "@attr2" "obj2"]
  [(m/re #"obj|oppas|dc" ?ns) . !segs ...]
  {:ns (m/keyword ?ns)
   :xsegs [(m/cata ($EXAMPLE !segs)) ...]}

  ($EXAMPLE (m/re #"@.*" ?val))
  {:kind :seg-attr :val ?val}

  ($EXAMPLE (m/re #"[^@].*" ?val))

  {:kind :seg-chld :val ?val}

  ($EXAMPLE ?val)
  {:kind :unknown :val ?val})
;; =>
{:ns :oppas,
 :xsegs
 [{:kind :seg-chld, :val "obj1"}
  {:kind :seg-attr, :val "@attr1"}
  {:kind :seg-attr, :val "@attr2"}
  {:kind :seg-chld, :val "obj2"}]}

noprompt04:07:32

You can do some exotic/interesting kinds of things with this.

ikrimael04:07:35

brilliant; both left side/right side with m/cata feel clean and easily grokkable for future me