meander

All things about https://github.com/noprompt/meander Need help and no one responded? Feel free to ping @U5K8NTHEZ
timothypratley 2019-10-28T01:59:49.111900Z

Pop quiz; how can I encode: (:k1 (:k2 (:k3 {:k4 "foo"}))) -> {:k4 "foo", :k3 {:k2 {:k1 ?v}}}

timothypratley 2019-10-28T02:02:41.113400Z

The important part being that (:k1 (:k2 (:k3 _))) -> {:k3 {:k2 {:k1 _}}} seemingly just reversing a list, but the nesting is tripping me up

noprompt 2019-10-28T04:39:56.113700Z

@timothypratley This is a fun one. 🙂

noprompt 2019-10-28T05:07:18.114400Z

@timothypratley I split it in to two rules.

noprompt 2019-10-28T05:07:19.114600Z

(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 _}}}}

noprompt 2019-10-28T05:08:20.114900Z

But at map at the bottom yields:

(rule-2 (rule-1 '(:k1 (:k2 (:k3 {:k4 "foo"})))))
;; =>
{:k3 {:k2 {:k1 {:k4 "foo"}}}}

noprompt 2019-10-28T05:24:24.115500Z

[meander/epsilon "0.0.311"] ☝️ Fixes bug with memory variables in keys.

noprompt 2019-10-28T05:24:26.115800Z

And with this.

noprompt 2019-10-28T05:24:38.116100Z

rule-1 can become

noprompt 2019-10-28T05:24:39.116400Z

(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]))

noprompt 2019-10-28T05:25:18.116600Z

(rule-2 (rule-1 '(:k1 (:k2 (:k3 {:k4 "foo"})))))
;; =>
{:k4 {:k3 {:k2 {:k1 "foo"}}}}

noprompt 2019-10-28T05:27:18.117400Z

That’s the best I can offer at the moment. 🙂

timothypratley 2019-10-28T12:02:14.118100Z

@noprompt marvelous!! Thank you very much!

eraserhd 2019-10-28T14:10:28.120100Z

@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.

eraserhd 2019-10-28T14:12:19.121500Z

e.g. (defstru exprs ?expr (+ ?expr ?expr) (- ?expr ?expr) (let [_ ?expr ...] ?expr))??

eraserhd 2019-10-28T14:13:42.123Z

Then (r/stru-topdown exprs (+ (- 4 (let [x 10] x))))? (Names are terrible & syntax is not actually proposed.)

eraserhd 2019-10-28T19:06:22.128300Z

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.

eraserhd 2019-10-28T19:07:29.128500Z

I mean, their values.

eraserhd 2019-10-28T19:08:21.128800Z

oh, I can bind the sequences to logic variables

eraserhd 2019-10-28T19:13:23.130400Z

except, I can't do something like (Union . (m/and (m/seqable _ ...) ?xs)) because the dot doesn't seem to work here.

eraserhd 2019-10-28T19:13:55.130800Z

(because it's really partition, not splice_)

noprompt 2019-10-28T19:38:18.131100Z

@eraserhd Whats the input data look like?

noprompt 2019-10-28T19:40:35.131800Z

Wait, duh, I can see it. 🙂

eraserhd 2019-10-28T19:40:42.132Z

heh.

eraserhd 2019-10-28T19:40:49.132300Z

I found a solution. Lemme paste.

eraserhd 2019-10-28T19:42:16.132900Z

https://gist.github.com/eraserhd/449ab98c03b99f8f333d585794def6f5 line 58, but the whole thing is interesting.

noprompt 2019-10-28T19:44:23.133300Z

Taking a look.

noprompt 2019-10-28T19:49:17.133500Z

Thats really cool.

noprompt 2019-10-28T19:52:09.133800Z

@eraserhd You can do this

(Intersection . (m/or Any !xs) ...)
(Intersection . !xs ...)

noprompt 2019-10-28T19:53:45.134400Z

(Intersection . (m/or (Intersection !xs ...) !xs) ...)
(Intersection . !xs ...)

eraserhd 2019-10-28T19:55:21.135200Z

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.

eraserhd 2019-10-28T19:55:31.135400Z

But, yes that's neat :)

noprompt 2019-10-28T19:56:05.136100Z

Since its bottom up you should be able to use cata right?

noprompt 2019-10-28T19:56:27.136500Z

(Intersection . (m/or (Intersection (m/cata !xs) ...) (m/cata !xs)) ...)
(Intersection . !xs ...)

noprompt 2019-10-28T19:57:50.137900Z

(m/with [%arg (m/cata (m/or (Intersection . !xs ...)
                            !xs))]
  (Intersection . %arg ...))
(Intersection . !xs ...)

eraserhd 2019-10-28T19:58:46.138400Z

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.

eraserhd 2019-10-28T19:59:19.138600Z

(in fact they often do)

eraserhd 2019-10-28T20:00:30.139500Z

cata on the right-hand-side might be nice here, though

noprompt 2019-10-28T20:00:40.139700Z

I’m actually working on that.

eraserhd 2019-10-28T20:00:45.140Z

I saw :)

noprompt 2019-10-28T20:00:51.140200Z

I’m hoping to have that working in the next day or two.

noprompt 2019-10-28T20:01:03.140500Z

I’m very close though.

eraserhd 2019-10-28T20:03:57.141400Z

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.

noprompt 2019-10-28T21:14:29.142700Z

Definitely throw some examples my way if you spot something not working.

noprompt 2019-10-28T21:15:09.143800Z

I haven’t run into anything with cata behaving badly that I didn’t patch right away.

noprompt 2019-10-28T21:15:30.144500Z

But I’ll be the first to admit that I probably haven’t tried it all.

eraserhd 2019-10-28T21:56:51.147Z

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! :)

noprompt 2019-10-28T21:58:28.147900Z

What happened?

eraserhd 2019-10-28T21:59:10.149200Z

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.

noprompt 2019-10-28T22:00:15.149500Z

Ah.

noprompt 2019-10-28T22:00:36.150100Z

It’ll be interesting to see how cata works out on the subst side.

noprompt 2019-10-28T22:00:46.150400Z

Because then you’ll be able to do reductions.

noprompt 2019-10-28T22:01:24.151300Z

There’s a bit of work involved but its possible to some interesting things once you have connections like that.

eraserhd 2019-10-28T22:01:31.151400Z

hmm, neat

noprompt 2019-10-28T22:02:08.152100Z

cata on the subst side applies substitution to its argument and the calls the catamorphism.

noprompt 2019-10-28T22:03:24.152700Z

(rewrite [2 1]
  [1 1] :Hello!
  [?x ?y] [?x (cata [?y ?y])])
;; => [2 :Hello!]

eraserhd 2019-10-28T22:05:47.154300Z

nice!

noprompt 2019-10-28T22:07:07.155900Z

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.

noprompt 2019-10-28T22:08:24.157400Z

I’ve been messing around with some of the ideas out of the interpreter world like Truffle and Lightweight Modular Staging.

noprompt 2019-10-28T22:08:38.157800Z

Seems like the big trick is to just have a better IR.

noprompt 2019-10-28T22:09:37.159Z

Its also much easier to wrap your head around than, say, the matrix style approach to pattern matching.

noprompt 2019-10-28T22:10:46.160100Z

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.