meander

All things about https://github.com/noprompt/meander Need help and no one responded? Feel free to ping @U5K8NTHEZ
yuhan 2020-03-31T02:02:19.062Z

Is this a bug?

(m/rewrite {}
  {:k (m/seqable !x ..!n)}
  {:k [!x ..!n]})
;; => {:k []}

(m/rewrite [{}]
  [{:k (m/seqable !x ..!n)} ...]
  [{:k [!x ..!n]} ...])
;; => []

timothypratley 2020-03-31T20:07:54.106500Z

@qythium @noprompt FWIW just wanted to add my 2c that I’ve encountered this and found that using named collectors is usually the ticket in my usage:

(m/rewrite [{}]
         [{:k (m/seqable !x ..!n)} ...]
         [{:k [!x ..!n]} ...])
=> []
(m/rewrite [{}]
         [{:k (m/seqable !x ..!n)} ..!m]
         [{:k [!x ..!n]} ..!m])
=> [{:k []}]
To me this seemed logical because I think of as disperse everything without context. /shrug

yuhan 2020-03-31T02:03:18.062500Z

Based on the first result I would expect the second to produce [{:k []}]

noprompt 2020-03-31T03:08:50.068800Z

@qythium I think so. This probably has something to do with how compiles.

noprompt 2020-03-31T03:12:08.070900Z

There’s a runtime check to see if the memory variables have been exhausted.

yuhan 2020-03-31T03:12:43.071400Z

I think I'll just avoid the ..!n construct entirely for now... it seemed so useful at first but it's just been a source of bugs and headaches 😕

noprompt 2020-03-31T03:13:56.072Z

I’m sorry about that and I agree with you.

noprompt 2020-03-31T03:15:55.074100Z

FWIW I’m working to make these problems go away.

1👍
noprompt 2020-03-31T03:16:47.075Z

But in this case its not the ..!n that is the problem its actually the in this case.

yuhan 2020-03-31T03:17:06.075600Z

no discouragement intended!

noprompt 2020-03-31T03:17:07.075800Z

Memory variables do not have this problem on zeta.

noprompt 2020-03-31T03:17:26.076400Z

Nor does .

noprompt 2020-03-31T03:18:02.077300Z

I think the mistake I made in epsilon down is trying to bind everything in Clojure.

noprompt 2020-03-31T03:18:38.078Z

The code comes out fast but its also been harder to debug.

noprompt 2020-03-31T03:19:16.078700Z

In zeta I decided to manage the bindings at runtime with a map.

noprompt 2020-03-31T03:20:16.080Z

Its slightly slower to execute a zeta pattern match but its also much easier to manage and iteratively improve than starting at the lowest level first.

yuhan 2020-03-31T03:22:39.081600Z

What slightly worries me about Zeta's bootstrapping is that if there are still correctness issues with the epsilon logic that's used to compile it, will that mean that it's all going to be a black box built on a uncertain foundation?

noprompt 2020-03-31T03:25:14.083100Z

I think thats a valid concern and thats why I patch epsilon.

noprompt 2020-03-31T03:26:23.084200Z

There’s little use of ..!n at the moment.

noprompt 2020-03-31T03:28:19.085500Z

90% of the parser/compiler stuff is built with logic variables. I do use a handful of memory variables but there’s no nesting.

noprompt 2020-03-31T03:29:04.086100Z

I’ll think about the best way to fix that bug in epsilon.

noprompt 2020-03-31T03:29:18.086400Z

If you have an idea for a patch that’d be good.

noprompt 2020-03-31T03:29:31.086800Z

I’m not sure if swapping out an or would be safe or not.

yuhan 2020-03-31T03:31:44.087600Z

Thanks! I probably can't help here, don't know much about the internals

noprompt 2020-03-31T03:33:17.088800Z

Thats fine. But I hope it gives you confidence know that I’m not trying to cut corners.

noprompt 2020-03-31T03:34:10.090200Z

The logic makes sense as: If epsilon has a bug And zeta uses epsilon to build zeta Then epsilon should be patched 🙂

noprompt 2020-03-31T03:34:21.090400Z

QED

noprompt 2020-03-31T03:34:23.090600Z

😛

noprompt 2020-03-31T03:34:56.091Z

And, also, I kind of depend on bug reports.

yuhan 2020-03-31T03:35:45.091200Z

will provide as many as I can 🙂

yuhan 2020-03-31T03:37:52.092100Z

unrelated question, what's the best way of providing "default" values for variables?

(m/rewrite {}
  {:k ?v}
  {:k ~(or ?v :default)})

yuhan 2020-03-31T03:38:24.092500Z

this works for logic vars but gives an error on

(m/rewrite [{}]
  [{:k !v} ...]
  [{:k ~(or !v :default)} ...])

noprompt 2020-03-31T03:51:49.093100Z

There’s always

(m/or pattern-containing-?x (m/let [?x :default]))

noprompt 2020-03-31T03:53:00.093800Z

Or

{:k (m/or (m/and nil (m/let [?x :default]))
          ?x}

yuhan 2020-03-31T03:53:53.094200Z

That doesn't seem to work for mem vars as well?

yuhan 2020-03-31T03:54:12.094500Z

(m/rewrite [{}]
  [{:k (m/or !v (m/let [!v :default]))} ...]
  [{:k !v} ...])
;; => [{:k nil}]

noprompt 2020-03-31T03:55:27.094800Z

(me/rewrite [{}]
  [{:k (me/or (me/let [!v :default]) !v)} ...]
  [{:k !v} ...])
;; =>
[{:k :default}]

noprompt 2020-03-31T03:56:25.096100Z

!v is [nil] in your example cause !v is matched against (get m :k)

yuhan 2020-03-31T03:56:32.096300Z

but that binds all !v to :default

yuhan 2020-03-31T03:56:48.096900Z

(m/rewrite [{:k :exists} {}]
  [{:k (m/or (m/let [!v :default]) !v)} ...]
  [{:k !v} ...])
;; => [{:k :default} {:k :default}]

noprompt 2020-03-31T03:57:12.097400Z

You want something like the example I gave

(m/or (m/and nil (m/let [!v :default]))
      !v)

noprompt 2020-03-31T03:57:45.097700Z

(me/rewrite [{} {:k "i have a value"}]
  [{:k (me/or (me/and nil (me/let [!v :default])) !v)} ...]
  [{:k !v} ...])
;; =>
[{:k :default} {:k "i have a value"}]

noprompt 2020-03-31T03:58:28.098200Z

You could do

(me/defsyntax default [match p clojure-expr]
  `(me/or (me/and ~match (me/let [~p ~clojure-expr])) ~p))
with maybe better name.

noprompt 2020-03-31T03:59:24.099200Z

(default nil ?x :default)
If the value matches nil pattern match ?x against :default otherwise pattern match with ?x.

yuhan 2020-03-31T04:02:03.099600Z

nice, thanks!

noprompt 2020-03-31T04:26:43.100600Z

Just noticed I wrote (or (or ,,,) ,,,) when I meant (or (and ,,,) ,,,)

noprompt 2020-03-31T04:41:47.101500Z

@qythium by switching that and to an or in the substitution compiler I get

(rewrite [{}]
  [{:k (seqable !x ..!n)} ...]
  [{:k [!x ..!n]} ...])
;; =>
[{:k []}]

noprompt 2020-03-31T04:42:11.101700Z

And

(rewrite {}
  {:k (seqable !x ..!n)}
  {:k [!x ..!n]})
;; =>
{:k []}

noprompt 2020-03-31T04:44:29.102400Z

There are two failures though

FAIL in meander.epsilon-test/subst-mvr-rp*-test (epsilon_test.cljc:2023)
expected: [[1 :a] [2 :b]]
  actual: [[1 :a] [2 :b] [3 nil]]
    diff: + [nil nil [3 nil]]

FAIL in meander.epsilon-test/subst-mvr-rp*-test (epsilon_test.cljc:2025)
expected: [[:a 1] [:b 2]]
  actual: [[:a 1] [:b 2] [nil 3]]
    diff: + [nil nil [nil 3]]
from these tests
(let [!1s [1 2 3]
      !2s [:a :b]]
  ,,,
  (t/is (= [[1 :a] [2 :b]]
           (r/subst [[!1s !2s] ...])))
  (t/is (= [[:a 1] [:b 2]]
           (r/subst [[!2s !1s] ...])))

noprompt 2020-03-31T04:46:46.103100Z

Maybe the check should only be looking at memory variables that are top-level to the

noprompt 2020-03-31T04:51:23.104900Z

Eh, but actually, I don’t think thats right either.

noprompt 2020-03-31T19:21:08.105900Z

Would m/recur be a better name than m/cata?

5➕
markaddleman 2020-03-31T19:40:00.106Z

I vote yes

timothypratley 2020-03-31T20:01:29.106200Z

+1

timothypratley 2020-03-31T20:07:54.106500Z

@qythium @noprompt FWIW just wanted to add my 2c that I’ve encountered this and found that using named collectors is usually the ticket in my usage:

(m/rewrite [{}]
         [{:k (m/seqable !x ..!n)} ...]
         [{:k [!x ..!n]} ...])
=> []
(m/rewrite [{}]
         [{:k (m/seqable !x ..!n)} ..!m]
         [{:k [!x ..!n]} ..!m])
=> [{:k []}]
To me this seemed logical because I think of as disperse everything without context. /shrug