meander

All things about https://github.com/noprompt/meander Need help and no one responded? Feel free to ping @U5K8NTHEZ
2020-03-10T10:59:02.129900Z

Hey! I am struggling to express a pattern. For instance we could have 1 even number followed by 0 or more odd numbers, this pattern repeating in a sequence like in [2 3 5 4 3 2]. The goal would be to get in this example something like [[2 [3 5]] [4 [3]] [2[]]] Any ideas ?

noprompt 2020-03-10T21:28:44.130400Z

There is a partial solution to this problem but, actually, what we really need to do this properly is a greedy version of (basically Kleene star which is not that). I would use vanilla Clojure for this in the interim.

2020-03-10T22:10:47.130600Z

Ok thanks, I gathered the pattern It has a regex feel to it, it might be expressed by (ab*)*. I had a partial solution that identify the first pattern, something like

(-> [2 3 5 4 5 3 6]
    (m/search
      (m/seqable (m/pred even? ?e) .
                 (m/pred odd? !os) ...
                 & (m/and ?rest
                          (m/or
                            (m/seqable)
                            (m/seqable (m/pred even?) .
                                       (m/pred (constantly true)) ...))))
      {:e ?e
       :os !os
       :rest ?rest}))
wondering if I could have use some catamorphism magic on ?rest but I am not used to meander yet and some operator are a little mind bending at first. Plus my solution feels a bit cumbersome compared to the regex. Now I know I can’t really express it. Thanks a lot!

noprompt 2020-03-10T23:12:45.130800Z

So the partial solution uses rewrite and cata but due to not having a greedy star or grouping it, and the way rewrite works presently I can’t, in honesty, recommend it.

(m/rewrite [2 3 5 4 3 2]
  [] []
  [(m/pred even? ?even) . (m/pred odd? !odds) ..!ns & ?rest]
  [[?even [!odds ...]] & (m/cata ?rest)])
;; => 
[[2 [3 5]] [4 [3]] [2 []]]
(It could use seqable here.) The zeta branch will have both grouping and greedy star. I think I can bring greedy star to epsilon but I’m not sure about grouping.

noprompt 2020-03-10T23:14:52.131Z

FWIW, I’m spending time working on zeta and less time on epsilon because its easier to build a better, less buggy implementation that reflects the breadth and depth of knowledge that I acquired while working on epsilon. In the spirit of transparency, I’m learning 🙂

timothypratley 2020-03-10T23:15:40.131800Z

True story I made this before seeing your cata:

(m/rewrite [2 3 5 4 3 2]
  (m/with [%p (m/or [(m/pred even? !x) . (m/pred odd? !y) ..!n & %p]
                    [])]
    %p)
  [[!x [!y ..!n]] ...])

timothypratley 2020-03-10T23:17:54.133500Z

oh damn, my verison drops the last thing though => [[2 [3 5]] [4 [3]]]

noprompt 2020-03-10T23:19:40.134400Z

FYI someone asked about having Mathematica’s Longest and we will have that in the form of greedy Kleene start both on epsilon and zeta.

1
noprompt 2020-03-10T23:20:29.135Z

In fact, zeta will basically have as much or all of regex as humanly possible.

timothypratley 2020-03-10T23:24:43.135100Z

@noprompt when you say “I can’t recommend it” about your m/cata solution…. why not? seems good to me???

timothypratley 2020-03-10T23:28:49.135400Z

Is it that “greedy Kleene” would be more efficient? concise? (Maybe I should just wait and see 🙂)

noprompt 2020-03-10T23:35:17.135600Z

@timothypratley is not greedy. You can think of as a gradient from the least to most amount of greed with respect to context. So its really designed for ambiguity when two or more patterns are next to each other.

noprompt 2020-03-10T23:36:11.135800Z

Greed is really about how much to consume and not so much about efficiency or concision.

noprompt 2020-03-10T23:37:16.136Z

For example

;; Using infix * to demo
[!xs * !ys ...]
;; or
[!xs * !ys *]
should always starve !ys by consuming everything because the semantics of * are greedy.

noprompt 2020-03-10T23:38:24.136200Z

The same would apply to + by comparison to ..1 . These are not expressing the same idea, at least to my mind they aren’t.

noprompt 2020-03-10T23:40:05.136400Z

*/`+` are for when you don’t want ambiguity while /`..N` would be.

noprompt 2020-03-10T23:40:48.136600Z

I must apologize to everyone on the face of the earth for not recognizing this subtle difference sooner. 🙂

timothypratley 2020-03-10T23:45:33.138100Z

Ah well I don’t disagree with you… but I’m not seeing how it affects expression of this particular problem. In this case it seems like greediness isn’t a factor as there is only one solution.

timothypratley 2020-03-10T23:46:29.138300Z

Don’t get me wrong; I love regexs and like the sound of what you are saying, I just don’t get it 😄

noprompt 2020-03-10T23:46:43.138500Z

There isn’t one solution to this

[(m/pred odd? !odds) ... & ?rest]

noprompt 2020-03-10T23:47:13.138700Z

Hence the need for an explicit distinction of greediness.

timothypratley 2020-03-10T23:47:25.138900Z

Oh I think I see what you mean now

noprompt 2020-03-10T23:47:33.139100Z

What we really want here is CONSUME ALL THE ODDS DAMMIT!!! 😂

noprompt 2020-03-10T23:47:49.139300Z

But because its ambiguous… hahah yeah. 😛

noprompt 2020-03-10T23:48:20.139700Z

I also want to thank everyone, again, for the millionth time for supporting the project and suffering lows. 🙂

noprompt 2020-03-10T23:48:38.139900Z

And sharing the highs. 😉

timothypratley 2020-03-10T23:49:13.140Z

is there a situation where you really want non-greedy? I guess for search maybe?

ezmiller77 2020-03-10T23:52:04.141200Z

Hey I’m wondering if it’s possible to extract the structures that one passes to the match function. Eg.. I tried something like this:

(def match `{:a ?a :b ?b})
(def target `{:a ?b :b ?a})
(m/match {:a 1 :2} ~match ~target}

noprompt 2020-03-10T23:52:38.141500Z

Yep. 🙂 And find too.

ezmiller77 2020-03-10T23:52:49.141700Z

This produced an error:

ezmiller77 2020-03-10T23:52:51.142Z

> non exhaustive pattern match

noprompt 2020-03-10T23:53:25.142200Z

Hence my apology for not noticing the subtlety

timothypratley 2020-03-10T23:54:26.143100Z

I guess somewhat ironically in match means non-greedy but in search means greedy if you have enough constraints o_O I know it doesn’t really mean greedy but you can make it behave like that obviously as per example.

timothypratley 2020-03-10T23:55:22.144300Z

defsyntax 🙂

noprompt 2020-03-10T23:55:44.144900Z

Hi @ezmiller77 👋 Someone opened a ticket with a similar structure a while back and the tl;dr to this is “no” and the reason why is that ~expr is an equality check against the match target with respect to the result of expr . Its not for splicing patterns.

noprompt 2020-03-10T23:56:32.145400Z

(m/match [20 30]
  [~(* 10 2) ~(* 10 3)]
  :yes)
;; => :yes

noprompt 2020-03-10T23:58:14.146500Z

There is work on going in the subsequent branch of the project, zeta, which will allow for this kind of programatic thing.

timothypratley 2020-03-10T23:58:15.146600Z

(m/defsyntax m [] '{:a ?a :b ?b})
=> #'happy.beaver/m
(m/defsyntax t [] '{:a ?b :b ?a})
=> #'happy.beaver/t
(m/match {:a 1 :b 2}
  (m)
  (t))
=> {:a ?b, :b ?a}

ezmiller77 2020-03-10T23:58:47.147400Z

I see. So basically my use-case here has to do with keeping code readable. So maybe I can just pack the expression inside another fn.

ezmiller77 2020-03-10T23:59:36.148700Z

I’m basically trying to use meander to do a large-scale remap of keys on a map, where I’m also adding a bunch of other keys with nil values.

ezmiller77 2020-03-10T23:59:57.149400Z

So both the lhs and rhs expressions are gonna be quite large.