Pop quiz; how can I encode:
(:k1 (:k2 (:k3 {:k4 "foo"})))
-> {:k4 "foo", :k3 {:k2 {:k1 ?v}}}
The important part being that (:k1 (:k2 (:k3 _)))
-> {:k3 {:k2 {:k1 _}}}
seemingly just reversing a list, but the nesting is tripping me up
@timothypratley This is a fun one. 🙂
@timothypratley I split it in to two rules.
(defn rule-1 [x]
(m/match x
(m/with [%rec (!ks (& (m/or %rec %end)))
%end (!ks ?v)]
%rec)
[!ks ?v]))
(defn rule-2 [x]
(m/match x
[[?x & ?rest] ?v]
(rule-2 [?rest {?x ?v}])
[[] ?v]
?v))
(rule-2 (rule-1 '(:k1 (:k2 (:k3 (:k4 _))))))
;; =>
{:k4 {:k3 {:k2 {:k1 _}}}}
But at map at the bottom yields:
(rule-2 (rule-1 '(:k1 (:k2 (:k3 {:k4 "foo"})))))
;; =>
{:k3 {:k2 {:k1 {:k4 "foo"}}}}
[meander/epsilon "0.0.311"]
☝️ Fixes bug with memory variables in keys.
And with this.
rule-1
can become
(defn rule-1 [x]
(m/find x
(m/with [%rec (!ks (& (m/or %rec %end)))
%end (!ks (m/or {!ks ?v} ?v))]
%rec)
[!ks ?v]))
(rule-2 (rule-1 '(:k1 (:k2 (:k3 {:k4 "foo"})))))
;; =>
{:k4 {:k3 {:k2 {:k1 "foo"}}}}
That’s the best I can offer at the moment. 🙂
@noprompt marvelous!! Thank you very much!
@noprompt catching up this morning, and I just read about the object calculus. If you are proposing some kind of meander feature where you declare tree structure pattern-like, and get a thing you can pass to some kind of implementation tree-seq, prewalk, or postwalk, that sounds really awesome.
e.g. (defstru exprs ?expr (+ ?expr ?expr) (- ?expr ?expr) (let [_ ?expr ...] ?expr))
??
Then (r/stru-topdown exprs (+ (- 4 (let [x 10] x))))
? (Names are terrible & syntax is not actually proposed.)
Hmm, interesting situation. I want to rewrite intersection-of-unions as unions-of-intersections, and I've got something like, (Intersection . !xs ... (Union . !as ...) . !ys ...)
as the match, and (Union . (Intersection . !xs ... . !ys ... . !as) ...)
, which doesn't work because !vars can't be used more than once.
I mean, their values.
oh, I can bind the sequences to logic variables
except, I can't do something like (Union . (m/and (m/seqable _ ...) ?xs))
because the dot doesn't seem to work here.
(because it's really partition, not splice_)
@eraserhd Whats the input data look like?
Wait, duh, I can see it. 🙂
heh.
I found a solution. Lemme paste.
https://gist.github.com/eraserhd/449ab98c03b99f8f333d585794def6f5 line 58, but the whole thing is interesting.
Taking a look.
Thats really cool.
@eraserhd You can do this
(Intersection . (m/or Any !xs) ...)
(Intersection . !xs ...)
(Intersection . (m/or (Intersection !xs ...) !xs) ...)
(Intersection . !xs ...)
The (r/repeat (r/some-bu .)) only terminates on failure, so I think these don't work because they can match then produce the same result.
But, yes that's neat :)
Since its bottom up you should be able to use cata
right?
(Intersection . (m/or (Intersection (m/cata !xs) ...) (m/cata !xs)) ...)
(Intersection . !xs ...)
(m/with [%arg (m/cata (m/or (Intersection . !xs ...)
!xs))]
(Intersection . %arg ...))
(Intersection . !xs ...)
Hmmm. I'm using r/repeat with r/some-bu because the right-hand-sides on line 23 and 44 might produce re-reducible expressions.
(in fact they often do)
cata on the right-hand-side might be nice here, though
I’m actually working on that.
I saw :)
I’m hoping to have that working in the next day or two.
I’m very close though.
I have an intuition that cata doesn't work when the rewrites stradle tree-depth-levels like this. However, I will certainly attempt it for science.
Definitely throw some examples my way if you spot something not working.
I haven’t run into anything with cata behaving badly that I didn’t patch right away.
But I’ll be the first to admit that I probably haven’t tried it all.
welp, I just spent a bunch of time isolating a problem with cata+search which is just me using it wrong and it working correctly, so good job! :)
What happened?
I am reducing all the search-found values to a final result outside of the search, but of course, m/cata doesn't do that.
Ah.
It’ll be interesting to see how cata works out on the subst side.
Because then you’ll be able to do reductions.
There’s a bit of work involved but its possible to some interesting things once you have connections like that.
hmm, neat
cata
on the subst side applies substitution to its argument and the calls the catamorphism.
(rewrite [2 1]
[1 1] :Hello!
[?x ?y] [?x (cata [?y ?y])])
;; => [2 :Hello!]
nice!
This addition will probably be one of the last I make to the epsilon
branch in terms of new features because the current tools to optimize it are, I think, reaching there maximum capacity.
I’ve been messing around with some of the ideas out of the interpreter world like Truffle and Lightweight Modular Staging.
Seems like the big trick is to just have a better IR.
Its also much easier to wrap your head around than, say, the matrix style approach to pattern matching.
I mean, once you understand the Maranget approach to pattern matching compilation its not too hard and its a decent way to approach something that has inductive/flat types.