Fork me on GitHub
#meander
<
2020-08-28
>
jeremys14:08:00

Hello, I have a noob question if you don’t mind. I have some code like this:

(def example {:a {:ret :int}
              :b {:ret :int}
              :c {:ret :bool}})
(reduce (fn [acc [k v]]
          (update acc k (fnil conj []) v))
        {}
        (m/search example
          {?v {:ret ?k}}
          [?k ?v]))
Which is a inversion of a map, sort of. I am wondering, is there some way to express this as a rewrite?

noprompt18:08:37

Use group-by for this. 🙂

(let [example {:a {:ret :int}
               :b {:ret :int}
               :c {:ret :bool}}]
  (group-by first (m/search example {?v {:ret ?k}} [?k ?v])))

Jimmy Miller18:08:47

Looks like those aren't quite equivalent. Going to take a look more at what is intended

noprompt18:08:21

Oops, yep you’re right

(let [example {:a {:ret :int}
               :b {:ret :int}
               :c {:ret :bool}}]
  (m/rewrite [example {}]
    [{?v {:ret ?k} & ?rest} ?out]
    (m/cata [?rest (m/cata (`append ?out ?k ?v))])

    (`append {?k [!vs ...] :as ?out} ?k ?v)
    {?k [!vs ... ?v] & ?out}

    (`append ?out ?k ?v)
    {?k [?v] & ?out}

    [_ ?out]
    ?out))
;; =>
{:int [:a :b], :bool [:c]}

jeremys18:08:31

Thank you for the answer! It’s funny squinting at it, it looks like logic programming to me. I don’t know the cata operator yet besides the vague idea of recursion. Now I see a bit better how it works and the trick building the append` list to recur is neat. Wouldn’t have found it myself that’s for sure. Thanks

noprompt18:08:21

Oops, yep you’re right

(let [example {:a {:ret :int}
               :b {:ret :int}
               :c {:ret :bool}}]
  (m/rewrite [example {}]
    [{?v {:ret ?k} & ?rest} ?out]
    (m/cata [?rest (m/cata (`append ?out ?k ?v))])

    (`append {?k [!vs ...] :as ?out} ?k ?v)
    {?k [!vs ... ?v] & ?out}

    (`append ?out ?k ?v)
    {?k [?v] & ?out}

    [_ ?out]
    ?out))
;; =>
{:int [:a :b], :bool [:c]}

Jimmy Miller18:08:58

@jeremys In general, right now in meander if you want to group things, the general answer is to use clojures means of grouping.

Jimmy Miller18:08:09

We hope to have a better answer in the future.

jeremys18:08:12

@jimmy Thank you, I’ll keep looking out to see what goodies you guys come up with. This project tends to dead/live lock processes in my brain but I find it very cool.