My current m/rewrite-like code uses a walk and an atom. The atom is state that I update to indicate where I have rewritten in order to correct adjacent nodes. I'm wondering what my options are with meander.
I'm guessing a custom strategy might work.
Is it expected that bottom-up loses metadata? top-down doesn't seem to (but it might do, just not from a position I care about)
Looks like all
doesn't preserve metadata.
I've opened a PR. Happy to be told "no" :) Love how extensible meander is with syntax & strategies, means I can solve this for me if it's not appropriate upstream.
Hi! I’m learning meander as a beginner, experimenting with a list of maps, containing nested maps. Some of the maps are missing the key for the nested maps, but I still want to match on them. When I do it like the source code below, the second element is unmatched. How can I define :prop2
as an optional match?
(m/search
[{:prop1 "x1"
:prop2 {:prop3 {:prop4 "y"}}}
{:prop1 "x2"}]
(m/scan
{:prop1 ?prop1
:prop2 {:prop3 {:prop4 ?y}}})
{:prop1 ?prop1
:y ?y})
I think you can use m/or with m/let
You'll need a value for y somehow if I remember correctly
@dominicm Tried playing with the code in that direction, but not immediately clear to me how to combine those
https://github.com/noprompt/meander/blob/e3118ed0571d4176a3804236a23f32ecefce7df8/doc/operator-overview.md#let this is a good example I think.
The problem you'll have is that you need to bind ?y
somehow (That's where m/let comes in!)
I’m happiest when people send me patches. 🙂
(m/search
[{:prop1 "x1"
:prop2 {:prop3 {:prop4 "y"}}}
{:prop1 "x2"}]
(m/scan
{:prop1 ?prop1
:prop2 (m/or
{:prop3 {:prop4 ?y}}
(m/let [?y 0] nil))})
{:prop1 ?prop1
:y ?y})
I try :)
What we need to do is make sure that we always have our logic variables bound. So ?y
needs to be bound to something. In this case I just made it zero.
But we also need the nil there because of how search works. Search looks for all possible ways to match. So without the nil, we would get these results.
({:prop1 "x1", :y "y"} {:prop1 "x1", :y 0} {:prop1 "x2", :y 0})
Without nil, both branches of our or can match, so we will get back both ways of matching.(nil here means that if we look up the key in the map, we will get nil)
You could also move the or out a level.
(m/search
[{:prop1 "x1"
:prop2 {:prop3 {:prop4 "y"}}}
{:prop1 "x2"}]
(m/scan
(m/or
{:prop1 ?prop1
:prop2 {:prop3 {:prop4 ?y}}}
(m/let [?y 0]
{:prop1 ?prop1
:prop2 nil})))
{:prop1 ?prop1
:y ?y})
You sent me a few! 😄
@ingesol ^
I’ll get a release out here w/in the next couple hours. I need to walk back some of the changes I made to the rewrite stuff as its not fully baked. I made the mistake of commit to epsilon
and just kinda procrastinated undoing it. 😛
I have a cli for opening prs, my workflow is pretty lightweight on top of it. I can sneeze and send a pr.
Do you have something to share on that front? That sounds cool!
Basically just hub cli
Fork followed by pull request will pop open vim with a pr prefilled with the last commit
I have to push to my remote, but that's in my muscle memory now. Hub gives it a consistent name.
@jimmy @dominicm Thanks, this really helps! So in general, when I have an optional key, the pattern is this:
(m/or ?foo
(m/let [?foo nil]
nil))
Which is understandable and all is well. Was just wondering if there is some specific syntax for the case of simple optional map keys (not nested)By default simple keys are optional. If you match with a logic variable on a key that doesn't exist. You will get nil bound to that variable.
There reason to doesn't work here is because you are matching something more specific than a logic variable. The pattern asserts that prop2 should be a map.