[meander/epsilon "0.0.356"]
• Fixes separated patterns producing too many answers when searching
• Documentation updates
• Add :as pattern
keyword arguments to m/keyword
and m/symbol
This is going to sound pushy, but it's actually half conversational and half curiosity... How's Zeta?
I’ve been distracted by issues with epsilon and haven’t had a chance to resume working on zeta. But unless much more comes up, I think its safe to say I’ll resume working on the branch.
Here’s a question: should match
just be find
that throws an error when nothing matches?
Whats motivating the curiosity?
Personally I don't think so. I like that match is restricted to things that are unambiguous.
Talking about code standards internally at work. I'm thinking the update in place will make my work on cinder much easier. But also just seeing the updates to epsilon and realizing I don't entirely understand how you work and transition. Nor do I understand all the goals of Zeta, and if you're reaching them.
Basically, until zeta
becomes the primary branch, I will continue to address epsilon
issues as they come up and I can fix them without breaking existing code.
To be clear, I am personally not invested in working on implementing and update-in-place operator because I’m satisfied with cata
for that. At the same time, I’m not opposed to having such an operator. @jimmy is interested in this too. Maybe the two of you could work together on a concept/implementation?
The goals of zeta
are to define a new AST for the syntax and to implement an interpreter/compiler that are semantically equivalent.
I thought Zeta made this easier, going to double check what I read 😊
Yeah, the hope from Jimmy was that Zeta will bring this in some manner. @jimmy totally happy to describe my problems in excruciating detail and get some guidance on how to solve that.
@noprompt what problems do those changes solve?
Epsilon could have update in place. There’s nothing stopping us there. Zeta is purely about a better AST, interpreter, and compiler.
Yeah, that was my general I interpretation which gets me wanting to work on this sooner.
There is plenty of room for additional innovation in the strategy namespace.
I welcome that.
Yeah I am happy to have someone else to help with brainstorming update in place. I'd love to see some ideas and think about implementation. I'd definitely love to hear about your problems and think about what currently exists and what we could build in epsilon. I said zeta simply because my hope is that it will make building that stuff trivial. (also happy to explain the experiment we are trying with zeta) @dominicm feel free to private message me and we can chat about it (might be busy over the weekend though).
Please share any good ideas you come up with in the channel. 😀
Of course
One thing that would be really cool and I’ve been wanting is to have a compiled, strategy thingy. Update in place would be nice to have.
Hi! I'm giving meander a try on some toy problems - it's a blast!
Would it be possible to partition-by
sequences with meander
? E.g.:
;; 0 is the separator
(meander-magic [1 2 3 0 4 5 6 0 7 8 0 9])
;; => ([1 2 3] [4 5 6] [7 8] [9])
Also, some questions I had while trying to solve this:
- Is there a way to make search
"consume" input? (not matching what was already caught by a previous search)
- Is there a start
/`end-of-sequence` marker? (making this example's boundaries simpler)
- Is there something akin to Mathematica's Longest
/`Shortest` (i.e. https://reference.wolfram.com/language/ref/Longest.html to force "eager" or "lazy" matching)but why not use just partition-by
?
> if you pre-processed the sequence to add a leading and trailing zero, then extracted all "between-zero"
Yup, but I'd call that "cheating" for the purposes of this exercise. (But that's precisely the role I was expecting the start
/`end-of-sequence` markers to play)
> but why not use just partition-by
?
We could extend that argument to the whole of meander
:)
And here's how something like Longest
would help (Mathematica - lists are {}
, ..
, ...
behave like you'd expect, :>
is just a (late) binding):
SequenceCases[list, {0..., els: Longest[Except[0]..], 0...} :> {els}]
=> {{1,2,3},{4,5,6},{7,8},{9}}
You could accomplish this with strategies by doing a reduction with them. But other than that I can't think of a way.
Thanks! It's still unclear how I'd approach that, though. If you already have the final solution, please don't worry about giving me spoilers :)
There is probably a more succinct way, but here is one example.
(def divide-out-zeros
(r/pipe
(r/rewrite ?xs [?xs [[]]])
(r/until =
(r/rewrite
[[] ?acc] ?acc
[[0 & ?xs] [!acc ...]] [?xs [!acc ... . []]]
[[?x & ?xs] [!acc ... . [!last ...]]] [?xs [!acc ... . [!last ... . ?x]]]))))
(divide-out-zeros [1 2 3 0 4 5 6 0 7 8 0 9])
I for one would like to hear more about Longest.
Seems like it would be nice to define the break token and non-break using with
… &
can’t appear at the start currently but tere is a proposal to allow that… maybe :as
does not bind the vector like I hoped.
oh this works for the last bit only:
(m/find [1 2 3 0 4 5 6 0 7 8 0 9]
[ ;;& [(pred (complement zero?)) ... :as !x]
_ ...
(m/pred zero?) ...
& [(m/pred (complement zero?)) ... :as !x]]
!x)
I think I’d like to be able to write:
(m/match [1 2 3 0 4 5 6 0 7 8 0 9]
(m/with [%break% (pred zero?)
%thing% (m/not %break%)]
[(m/group (m/group %thing% ... :as !x) . %break% ...) ...])
!x)
(doesn’t work)
or
(m/match [1 2 3 0 4 5 6 0 7 8 0 9]
(m/with [%break% (pred zero?)
%thing% (m/not %break%)]
[& [& [%thing% ... :as !x] . %break% ...] ...])
!x)
(almost but not quite)it seems one way to look at this is that grouping would solve it, and &
provides grouping.
Figured out a solution with with
(m/rewrite [1 2 3 0 4 5 6 0 7 8 0 9]
(m/with [%split (m/or [!xs ..!n 0 & %split]
[!xs ..!n])]
%split)
[[!xs ..!n] ...])
Honestly don't know why I didn't think of this before. It isn't too bad at all.
Oh nice!!!! 🙂
(me/search '[a b c d e f g]
(me/and [!xs ..?i !ys ..?j !zs ..?k]
(me/guard (and (< ?i ?j)
(< ?k ?j))))
[!xs !ys !zs])
;; =>
([[] [a b c d] [e f g]]
[[] [a b c d e] [f g]]
[[] [a b c d e f] [g]]
[[] [a b c d e f g] []]
[[a] [b c d e] [f g]]
[[a] [b c d e f] [g]]
[[a] [b c d e f g] []]
[[a b] [c d e] [f g]]
[[a b] [c d e f] [g]]
[[a b] [c d e f g] []]
[[a b c] [d e f g] []])
☝️ Using the example as reference. Note that the search results include the solution given by the example.Here's the closest I could get, but I can't find my way around the sub-sequences being returned as well
(m/search [1 2 3 0 4 5 6 0 7 8 0 9]
(m/or
(m/scan
(m/pred (complement zero?) !els) ..1
. (m/pred zero?) ...)
(m/scan
(m/pred zero?) ..1
(m/pred (complement zero?) !els) ..1))
!els)
;; => ([1] [1 2] [1 2 3] [1 2 3] [2] [2 3] [2 3] [3] [3] [4] [4 5] [4 5 6] [4 5 6] [5] [5 6] [5 6] [6] [6] [7] [7 8] [7 8] [8] [8] [9] [4] [4 5] [4 5 6] [7] [7 8] [9])
NB: It's completely understandable that this might be the wrong tool for the job... but I can't help it.Compiled strategy?