This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-07-08
Channels
- # announcements (5)
- # aws (15)
- # babashka (7)
- # beginners (138)
- # bristol-clojurians (2)
- # chlorine-clover (11)
- # cider (9)
- # clara (4)
- # clj-kondo (17)
- # cljsrn (20)
- # clojars (1)
- # clojure (73)
- # clojure-europe (17)
- # clojure-italy (1)
- # clojure-nl (9)
- # clojure-spec (4)
- # clojure-uk (9)
- # clojurescript (43)
- # data-science (1)
- # datomic (87)
- # emacs (2)
- # figwheel-main (30)
- # fulcro (71)
- # helix (2)
- # hugsql (4)
- # jackdaw (5)
- # jobs (3)
- # jobs-discuss (31)
- # juxt (5)
- # kaocha (6)
- # lein-figwheel (16)
- # leiningen (1)
- # luminus (4)
- # malli (2)
- # meander (54)
- # music (8)
- # nrepl (12)
- # observability (28)
- # off-topic (85)
- # pathom (11)
- # re-frame (99)
- # reitit (9)
- # ring (1)
- # rum (6)
- # sci (11)
- # shadow-cljs (102)
- # sql (22)
- # tools-deps (10)
- # vim (65)
- # xtdb (14)
@noprompt @jimmy I added my first example with questions: https://github.com/noprompt/meander/pull/125/commits/556320934a6059fbff8c5bb986a1e8eb431352b2?short_path=4b806e6#diff-4b806e6fe29c6781cf8d51d441d3b4a9
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
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.
heh, fwiw, they were super helpful! also made me realize the docs didn't include the full api
Yeah, there’s a lot there and I generally don’t follow implementation updates, etc. with doc updates (I should, I know).
meta-comment: i think also helpful is more philosophical comment/feedback of "should meander even be used for this scenario?"
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)
A meander group-by
often comes up and the recommendation has always been to just use group-by
.
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
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.
With rewrite
you can do the (m/app #(->OppathSeg :seg-attr %1) !seg)
on the right side.
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
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)
I’ve been catching up on some research and experimenting with how to model, compile, interpret, etc.
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
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
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"}]}
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})
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?
@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 🙂)
@U5P29DSUS Reach out when you get stuck. If I can help, I will. 🙂
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.
@U5P29DSUS hah! exactly what i'm using it (albeit targetted towards C/C++)
parse decorated c/c++ => highlevel IR => clojure does term rewriting/inline expansion/etc => codegen c/c++ & UI bindings => JIT back into the app/editor
@markaddleman Cata on the right side can be used to construct a value to be recursively rewritten. It’s the dual of the left.
Ah, of course. Thanks
(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"}]}