+1 on group by; @jatkin how're you using m/gather? i couldn't get it to work the way i thought it would (i.e. with maps)
(m/search [{:a :whatever :b [{:n 1} {:n 2} {:n 1}]}
{:a :goes :b [{:n 1} {:n 2} {:n 4}]}
{:a :here :b [{:n 2} {:n 2} {:n 3}]}]
(m/scan {:a ?a :b (m/gather {:n !n})})
{:a ?a :n !n})
This did an ordered powerset of nimho, that's a great candidate to go into the cookbook
Sure - only thing is I don't fully grok why this did what it did
haha, neither do I. i'm playing with it right now
The gather there wouldn't be necessary. On my phone but you should be able to do [pattern ...]
Yup, you are right
Gather is filter for pattern matching. Given a pattern it will go through a sequence and find all the elements that match ignoring the others.
Oh --- and that's how I got a powerset
well, got 2 things to add now
some thoughts from weekend code sesh where i ended up rewriting a lot of meander matching:
handwavy/food for thought:
- cata
is really powerful especially on the right hand side.
- i can almost write shape morphing functions fluently which is a joy (i.e. don't need to lookup syntax and I can write it in one go)
- but debugging is such a pita when i get something wrong that i found myself psychologically building stuff out much slower and more methodically. just odd irrational human behavior so only verbalizing it as food for thought
- not really sure what's actionable here bc highlighting cata more upfront would probably showcase value earlier on but that's me looking at it with the "curse of knowledge" bias in that i understand the syntax enough.
more concrete thoughts:
- i find myself wanting to construct or extract a key out of a map alot with m/rerwrite but doing it inside of meander is frictive enough that i end up cheating and adding (let [helperfn .....])
can you elucidate on how this is different than the "normal" way?
ex: [ (m/app bla) ...]
or [pattern ...]
also is it meant to be used with maps?
It is used on seqables. Gather is often used with pred. So you could use gather with (m/pred even?) To gather up all the even numbers. Where as doing it with ... would require everything to be an even number.
Gather has a (m/or pattern _)
inside it. It does a little bit more than that though to handle more advanced repeat cases.
i think i'm missing something bc i'm still seeing it as (gather (pred even?)
== syntactic sugar for [(pred even?) ...]
?
except with the latter, that form also allows for dealing with maps
Imagine the sequence were [1 2 3]. The former expression would match. The latter would not because they are not all even numbers.
Gather has nothing to do with maps. It is just matching on seqables using m/seqable
Gather is almost syntatic sugar for (seqable (or pattern _) ...)
👍 ah right right. i keep blurring when things are exhaustive matches vs. not
i think i've hit [(pred even?) ...]
=> not doing what i just thought it did
and then replacing it with scan
and changing match to find or search until something works 😛
caveat: i just recently discover m/map-of and m/submap-of
which (correct me if i'm wrong) are the map equivalents for gather
Yep. That is why I came up with gather. I found myself doing the same thing and realized most of the time I wanted a simple filter.
(btw, i've added all this info to the cookbook so it'll be in a PR in a week or so)
------------------
ah, also one more addition: i think it'd be great if there was a m/gather
for maps
e.g. if m/submap-of
can be used with :as
to capture the result of the submap filter
At the time map-of
/`submap-of` was added, the inverse of this was suggested e.g. a way to capture the part of that map that didn’t match. I think both are useful and supportable.
From my point of view this is yet more support for the idea that “folds”, as I have discussed them, are primitive and relevant i.e. these two problems are symptoms of the same underlying condition which is that we do not have a way to bind with reduction.
Binding, in theory sense, is a sort of reduction operation that can fail. Logic variables bind values when they are unbound and fail when an attempt is made to bind them to a logically inequivalent value. Memory and mutable variables always bind. It makes sense [to me] that reduction be exposed to allow for binding to be rich and powerful.
> i find myself wanting to construct or extract a key out of a map alot with m/rerwrite but doing it inside of meander is frictive enough that i end up cheating and adding `(let [helperfn .....]) Got an example of this? Really curious to understand more.
sure (heads up, picked this bc its more convoluted than it needs to be but is a real snippet where I just "gave up in frustration" after wrestling with it for a couple hours)
https://gist.github.com/ikrima/c114ebf0450a56073ad0431716135530
really the important bits:
i have a feeling most of these issues are a symptom of lack of "gather" for maps (cx - the submap-of
thread)
And I run into it more bc i'm using rewrite and thus using meander syntax to create vs. normal clojuree
----------------- oops, forgot to add what i wanted the code to do:
(xfm
;; Operator Type Decl
{:in {:fldname {:name ?name :ctype ?ctype :initval ?dlftval } ...}
:out {:fldname {:name ?name :ctype ?ctype :initval ?dlftval } ...}}
;; Map of Init Values
{:fldname ?fldinitval }
;; Result =>
{:prmin {{:prmName ?name :prmType ?ctype :prmBind (or ?fldinitval ?dlftval :prmBindNone) }}
:prmout {{:prmName ?name :prmType ?ctype :prmBind (or ?fldinitval ?dlftval :prmBindNone)}}}
)
-----
highlevel: it's usually around map construction on the right hand side e.g.
- merge mapA mapB
- update mapA's values from mapB
- variations of "cartesian/relational" operations ie canonical sql join/filter/etc