Fork me on GitHub
#beginners
<
2016-10-29
>
olegakbarov11:10:58

Guys, does this looks like an idiomatic Clojure? I’m mostly interested in keeping state in atoms

(defn threads->frames [coll]
  (let [tmp (atom {:frames []})
        index (atom 0)]
    (reduce
     (fn [acc item]
       (if (contains? item :buttons)
         (do
           (swap! index inc)
           (swap! tmp update-in [:frames] conj item)
           (let [new-acc (conj acc @tmp)]
             (reset! tmp {:frames []})
             new-acc))
         (do
           (swap! index inc)
           (swap! tmp update-in [:frames] conj item)
           (if (= @index (count coll))
             (conj acc @tmp)
             acc))))
     []
     coll)))

dominicm13:10:33

@olegakbarov: You could separate the updating of state, and the generation of the new version, I think it would make your code simpler. But I haven't fully understood your code yet. Doesn't feel very idiomatic to be messing with atoms repeatedly via a reduce though.

olegakbarov13:10:53

Yeah, same feelings

rauh13:10:13

What does it try to do? I would also agree that it's not very idiomatic

rauh13:10:20

can you provide ex. input/output

olegakbarov13:10:22

But i cant wrap my head around how to make this without this “statefulness"

olegakbarov13:10:11

(def input
  [{:id 1 :buttons []}
   {:id 2}
   {:id 3 :buttons []}
   {:id 4 :buttons []}
   {:id 5}
   {:id 6}])

=> 

[[{:id 1 :buttons []}]
 [{:id 2} {:id 3 :buttons []}]
 [{:id 4 :buttons []}]
 [{:id 5}{:id 6}]]
The idea here is to pack items with field :buttons as last in batch

rauh13:10:58

I see, you'll need to partition probably

dominicm13:10:44

^^ partition is what I was just looking at.

rauh13:10:05

@dominicm There is a few useful partition variations out there

rauh13:10:42

I have partition-after and partition-at or partition-when is quite common

rauh13:10:54

I'll gist the partition-after which you'd need

olegakbarov13:10:55

would be awesome to see!

rauh13:10:26

You'd then do:

(into []
      (comp
        (partition-after #(contains? % :buttons))
        (map #(-> {:frames %})))
      xx)

olegakbarov14:10:05

thanks! need some to for this to sink in

dominicm14:10:07

That's quite a lot of code..

dominicm14:10:17

(defn new-threads->frames [coll]
  (map
    #(hash-map :frames %)
    (reduce
      (fn [acc item]
        (let [h (butlast acc)
              l (last acc)]
          (if (contains? (last l) :buttons)
            (concat acc [[item]])
            (concat h [(concat l [item])]))))
      []
      coll)))
Works for this specific case.

dominicm14:10:34

It's a trade-off of utility though there. Which is variant in projects I find.

olegakbarov14:10:22

Oh, now i know about butlast !