meander

All things about https://github.com/noprompt/meander Need help and no one responded? Feel free to ping @U5K8NTHEZ
jimmy 2019-12-13T00:11:50.488700Z

(seqable &lt;pattern&gt; ...) is like [<pattern> …] but works for anything in clojure that is seqable. That means that everything in the collection must match that pattern. (scan &lt;pattern&gt;) actually expands to something like [_ ... &lt;pattern&gt; . _ ...]. Scan is looking for anywhere in the collection that the pattern could exist. Scan actually allows you to try and match on multiple patterns. It will search through the collection finding all the elements that can match your pattern and ignore all the rest. Scan must be used with search Finally (gather &lt;pattern&gt;) says find me all the things in the collection that match this pattern and gather them up for me. Anything that doesn’t match I don’t care about it. I should think about writing an article explaining these. None of them are actually primitive. They are things we have found useful and added to meander, but they are all just extensions built on top of the base.

1👍
2019-12-13T00:29:52.489Z

This is helpful. Thanks. I noticed an Github issue to write a top-down tutorial. I think that would help me a lot. It's been a long time since term rewriting systems in school and I'm finding it hard to see the forest for the trees.

eraserhd 2019-12-13T01:04:33.489200Z

It's generally doing logic programming on a large map... I want to find all x such that y and z, with joins across the map. So yes.

eraserhd 2019-12-13T01:12:43.489400Z

Two possible solutions:

eraserhd 2019-12-13T01:13:07.489600Z

1. The naive parsing. If a variable which could be bound is mentioned in the body, make it bound first.

eraserhd 2019-12-13T01:13:25.489800Z

This would be wrong if we let-bind a variable name which is bound elsewhere.

eraserhd 2019-12-13T01:14:25.490Z

2. Metadata on the function indicating what it needs (in other words, manual).

eraserhd 2019-12-13T01:17:37.490400Z

3. A new syntax, (m/app' f pat &amp; args), where no variables are bound during compilation of f, and f is applied to the match value and the args (which could be already-bound) and matched to pat.

noprompt 2019-12-13T01:18:52.491100Z

We could also try giving logic variables a priority.

noprompt 2019-12-13T19:57:56.000300Z

@eraserhd I’m thinking about #3 a bit now. What do you think of this sketch?

(m/compute ?result + ?a ?b)
;; `?a` and `?b` must be bound
;; `?result` matches the result of the function application.

noprompt 2019-12-13T19:58:43.000500Z

This is venturing near constraint territory.

noprompt 2019-12-13T19:59:02.000700Z

(m/compute true &lt; ?a ?b)

eraserhd 2019-12-13T20:06:14.000900Z

hmm.

eraserhd 2019-12-13T20:07:45.001100Z

This is pretty close to m/let.

eraserhd 2019-12-13T20:08:51.001300Z

m/let presumably has the same problems as m/app wrt captured variables?

eraserhd 2019-12-13T20:16:01.001500Z

I think m/compute is slightly awkward.

eraserhd 2019-12-13T20:16:15.001700Z

I wouldn't bat an eye if that's what I got.

eraserhd 2019-12-13T20:18:25.001900Z

(m/compute ?result (+ ?a ?b)) feels slighty better. In this example, only a list with simple subexpressions is allowed.

eraserhd 2019-12-13T20:20:02.002100Z

There's a form like this in Datomic. It's not clearly defined what is allowed in subexpressions in Datomic, and occasionally I can get away with something useful, but not much.

eraserhd 2019-12-13T20:20:22.002300Z

In Datomic, [(+ ?a ?b) ?result].

eraserhd 2019-12-13T20:21:09.002500Z

IIRC, [(+ ?a (+ 1 2)) ?result] works, but [(+ ?a (+ 1 ?b)) ?result] does not.

eraserhd 2019-12-13T20:21:15.002700Z

(variables have to be at the top)

eraserhd 2019-12-13T20:23:22.002900Z

And, I guess this is just let with a rule that any variables are at the top.

noprompt 2019-12-13T20:42:54.003100Z

I think something like

(m/compute result-pattern fn-pattern arg-patterns ...)
might be have some useful properties because fn-pattern can be bound to a fn from Clojure explicitly
(m/compute ?res ~+ ?a ?b)

noprompt 2019-12-13T20:43:30.003300Z

Its not clear to me what extra round braces provide.

noprompt 2019-12-13T20:45:03.003600Z

To be clear, I’m thinking of what the primitive form of this would be.

eraserhd 2019-12-13T20:45:22.003800Z

ah

noprompt 2019-12-13T20:46:07.004Z

Because I think m/app would emerge from this easily.

noprompt 2019-12-13T20:46:10.004200Z

(m/app inc ?res)
;; ==
(m/compute ?res ~inc)

eraserhd 2019-12-13T20:46:59.004400Z

Must all args, aside from f, be logic or memory variables?

noprompt 2019-12-13T20:47:07.004600Z

But also, we could get constraints out of this too.

noprompt 2019-12-13T20:47:19.004800Z

No.

noprompt 2019-12-13T20:47:36.005Z

(m/compute 2 ~+ 1 1) ;; matches
(m/compute 3 ~+ 1 1) ;; fails

eraserhd 2019-12-13T20:48:04.005300Z

Ok, then I like this.

noprompt 2019-12-13T20:48:31.005500Z

And if you would like round braces, of course, you could syntax that on later.

eraserhd 2019-12-13T20:48:43.005700Z

right

eraserhd 2019-12-13T20:50:07.005900Z

1. wacky idea - it's possible to attach metadata to things such that + could be reversible - e.g. ?result bound, but an arg not. Although, I guess that's also not a primitive?

eraserhd 2019-12-13T20:50:15.006100Z

2. does "constraints" imply unification?

noprompt 2019-12-13T20:50:37.006300Z

Maayybe.

eraserhd 2019-12-13T20:51:15.006500Z

hrmm. I can't think of a use for it. But I shall pay more attention.

noprompt 2019-12-13T20:52:06.006700Z

There have been a few cases of people talking about patterns like

(m/and ,,, (m/guard (&lt; 1 ?y)))

noprompt 2019-12-13T20:56:19.006900Z

Regarding unification, I’ve been wanting to venture more into that territory because there’s a lot of power there and whole bunch of stuff falls out. Pattern matching is a special case of unification where one of the terms being unified is ground.

noprompt 2019-12-13T21:00:29.007100Z

Back to 1. no that isn’t wacky but it would probably mean that we’d need to talk about domains.

noprompt 2019-12-13T21:02:12.007300Z

Which, honestly, that’s going to have to happen anyway.

noprompt 2019-12-13T21:04:34.007500Z

Because substitution currently does not have a failure semantic and it only computes a single result. We have an open ticket for generating values, this is essentially the search version of subst . A primary reason it hasn’t be started is that in order to do so a notion of failure is required.

eraserhd 2019-12-13T21:05:12.007700Z

hmm

eraserhd 2019-12-13T21:05:33.007900Z

that's kind of neat

noprompt 2019-12-13T21:06:15.008100Z

I think so too. 🙂 Shapes are kind of trippy.

eraserhd 2019-12-13T21:06:16.008300Z

this reminds me of a completely different use case I have - testing. The problem here is that it needs much better error messages.

noprompt 2019-12-13T21:06:28.008500Z

Totally!

eraserhd 2019-12-13T21:07:30.008700Z

btw, I read syntax.clj and some of ir.clj. Which, historically, predicts I'll contribute in a few weeks.

eraserhd 2019-12-13T21:07:54.008900Z

cljc :D

noprompt 2019-12-13T21:08:08.009100Z

Its a bit of a mess in there. I’m sorry. I tried to keep it tidy while also trying to push out code for Clojurist Together.

noprompt 2019-12-13T21:08:32.009300Z

I’ve started some work on the zeta branch; the pace there will be much slower.

noprompt 2019-12-13T21:09:15.009500Z

But epsilon is going to be around for a while longer and it’d probably be a good idea to make an issue or two for some of the design problems therein.