Fork me on GitHub
#meander
<
2020-03-29
>
noprompt00:03:55

In this case the usual recommendation is to do the group-by first and then your processing after.

(let [data [{:class :a, :numbers [10], :count? true} 
            {:class :b :numbers [3], :count? true} 
            {:class :a, :numbers [88], :count? true}]]
  (m/find (group-by :class data)
    {?class [(m/or {:numbers [!nums ...] :count? true} _) ...] & (m/cata ?rest)}
    (cons {:class ?class :numbers (reduce + !nums) :count? true} ?rest)

    {}
    ()))
;; =>
({:class :a, :numbers 98, :count? true}
 {:class :b, :numbers 3, :count? true})

noprompt00:03:20

Aggregation is something that comes up a lot and we will have something specifically for it available by summer (along with other things).

JAtkins02:03:15

Thanks for the tip!

yuhan11:03:02

I spent some time tracking down a bug last week that turned out to be due to my use of the (and !memvar1 !memvar2) method from the cookbook for re-using a memvar in two different places in the output pattern, coupled with the ..!n syntax

yuhan11:03:38

something like [(m/and !m1 !m2) ..!n] -> {:a [!m1 ..!n] :b [!m2 ..!n]} , except nested in a much more complicated pattern

yuhan11:03:54

The bug was pretty obvious once discovered but it occured to me that such constructs can be pretty hard to reason about in subtle ways.. with an imperative flavour of pushing and popping from arrays and keeping track of indices

yuhan14:03:08

The next logical step is asking whether there exists some sort of ..(and !n1 !n2) syntax , but that just seems like a further step in the wrong direction..

yuhan14:03:28

really the [[!x ..!n] ...] syntax is a way of fitting multidimensional data into a linear memory variable, I wonder if there could be a less clunky way of encoding this

Jimmy Miller16:03:46

With fold and unfold we will have more power to implement better ways of doing these things. But my recommendation is also to dream up your ideal way and share it. Maybe it will be implemented or maybe it will spark other with more ideas.

noprompt16:03:17

Ideas are absolutely welcome.

niclasnilsson17:03:33

Question about variable number of forms:

;; This works:
(def data
  '((path "/a" 
          (PUT "Updates A"))
    (path "/b" 
          (GET "Gets a B"))))

(m/rewrite 
  data
  ((path !path (!method !desc)) ..!paths)
  [{:path !path
    :routes 
    {:method !method
     :desc !desc}} ..!paths])
  
;; But this was harder, when adding more routes to a path:
(def data
  '((path "/a" 
          (PUT "Updates A"))
    (path "/b" 
          (PUT "Gets a B")
          (PUT "Updates B"))))

;; Desired output
[{:path "/a" :routes [{:method 'PUT :desc "Updates A"}]}
 {:path "/b" :routes [{:method 'GET :desc "Gets a B"}
                      {:method 'PUT :desc "Updates B"}]}] 
I’ve tried to make it seqable and some other things, but can’t find the way to make this work. What am I missing?

noprompt18:03:45

@niclasnilsson

(let [data
      '((path "/a" 
              (PUT "Updates A"))
        (path "/b" 
              (PUT "Gets a B")
              (PUT "Updates B")))]
  (m/rewrite 
    data
    ((path !path . (!method !desc) ..!routes) ..!paths)
    [{:path !path
      :routes [{:method !method
                :desc !desc} ..!routes]} ..!paths]))
;; =>
[{:path "/a",
  :routes [{:method PUT, :desc "Updates A"}]}
 {:path "/b",
  :routes [{:method PUT, :desc "Gets a B"}
           {:method PUT, :desc "Updates B"}]}]

noprompt18:03:36

Keep in mind you can always use cata to do nested transforms with separate rules rather than all in one shot.

niclasnilsson18:03:19

Ah… I was more or less in dot from finding the solution then! Close, but no cigar! 🙂 Thank you very much, @noprompt!

👍 4