Fork me on GitHub
#meander
<
2020-07-26
>
ikrimael15:07:53

+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)

JAtkins16:07:04

(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 n

šŸ¤Æ 3
ikrimael16:07:05

imho, that's a great candidate to go into the cookbook

JAtkins16:07:36

Sure - only thing is I don't fully grok why this did what it did

ikrimael16:07:51

haha, neither do I. i'm playing with it right now

Jimmy Miller16:07:28

The gather there wouldn't be necessary. On my phone but you should be able to do [pattern ...]

JAtkins16:07:43

Yup, you are right

Jimmy Miller16:07:00

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.

ikrimael16:07:29

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?

Jimmy Miller16:07:01

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.

Jimmy Miller16:07:41

Gather has a (m/or pattern _) inside it. It does a little bit more than that though to handle more advanced repeat cases.

ikrimael16:07:04

i think i'm missing something bc i'm still seeing it as (gather (pred even?) == syntactic sugar for [(pred even?) ...] ?

ikrimael16:07:48

except with the latter, that form also allows for dealing with maps

Jimmy Miller16:07:06

Imagine the sequence were [1 2 3]. The former expression would match. The latter would not because they are not all even numbers.

Jimmy Miller16:07:58

Gather has nothing to do with maps. It is just matching on seqables using m/seqable

Jimmy Miller16:07:34

Gather is almost syntatic sugar for (seqable (or pattern _) ...)

ikrimael17:07:05

šŸ‘ ah right right. i keep blurring when things are exhaustive matches vs. not

ikrimael17:07:10

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 šŸ˜›

ikrimael17:07:21

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

Jimmy Miller17:07:24

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.

ikrimael17:07:59

(btw, i've added all this info to the cookbook so it'll be in a PR in a week or so)

šŸ‘ 6
JAtkins16:07:19

Oh --- and that's how I got a powerset

JAtkins16:07:42

well, got 2 things to add now

ikrimael16:07:45

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 .....])

šŸ’Æ 3
Jimmy Miller20:07:40

> 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.

ikrimael20:07:55

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)

ikrimael20:07:31

really the important bits:

ikrimael20:07:59

i have a feeling most of these issues are a symptom of lack of "gather" for maps (cx - the submap-ofthread) And I run into it more bc i'm using rewrite and thus using meander syntax to create vs. normal clojuree

ikrimael21:07:46

----------------- 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

Jimmy Miller03:07:55

Here are at least two things you can do to make this a tad bit more percise. First you can just use get directly, rather than binding a function.

(defn oprmbinds-mk [a_arg]
  (m/rewrite a_arg
    (:makeparmbinds ?valmap [{(m/or :name :fldname) (m/and !prmn1 !prmn2 !prmn3)
                              :ctype                {:ctuid !prmctuid}} ...])

    (m/map-of !prmn1  {:prmName  !prmn2
                       :prmCtuid !prmctuid
                       :prmBind  (m/app get ?valmap !prmn3 :prmbnd-none)})))
But technically, you donā€™t even need the get, maps are functions themselves.
(defn oprmbinds-mk [a_arg]
  (m/rewrite a_arg
    (:makeparmbinds ?valmap [{(m/or :name :fldname) (m/and !prmn1 !prmn2 !prmn3)
                              :ctype                {:ctuid !prmctuid}} ...])

    (m/map-of !prmn1  {:prmName  !prmn2
                       :prmCtuid !prmctuid
                       :prmBind  (m/app ?valmap !prmn3 :prmbnd-none)})))
I tried doing this with rewrites, and there is definitely a way, but I still ended up using the same little app trick. As for joins and stuff, those work fairly well with search/rewrites unless you want to do things like a default value if something doesnā€™t exist (like you are doing here). I played with trying to make it work with an explicit join and sadly came up a bit short. Through the m/app trick above would work, I was sad I couldnā€™t express it more directly.
(into {}
      (m/rewrites a_arg

        (:makeparmbinds {?param ?val} 
                        (m/scan {(m/or :name :fldname) ?param 
                                 :ctype {:ctuid ?prmctuid}}))
        [?param {:prmName ?param
                 :prmCtuid ?prmctuid
                 :prmBind ?val}]))

šŸ‘ 3
ikrimael18:07:07

------------------ 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

šŸ‘ 3
noprompt20:07:12

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.

šŸ‘ 3