0

I'm using re-frame, and I have a bind an atom to my-collection like this:

my-collection (atom {:one [] :two [] :three [] :four [] :five [] :six [] :seven [] :eight []})

Then I dispatch it to assoc to db and later, I will subscribe to it to use in a doseq like this:

(doseq [each (:one my-collection)]
    (if)

    (if)

    (if)
 )

Ther are now 8 doseq which I'm trying to put it on maybe a loop to avoid writing long doseq for 8 times. How can I do that?

I've tried this but it does not work:

(let [parts [:one :two :three :four :five :six :seven :eight]
      index (atom 0)]

    (loop [each ((nth parts @index) my-collection)]
        (do
            (if (= :one (nth parts @index)
            some code)

            (if (= :four (nth parts @index)
            some code)

            (if (= :eight (nth parts @index)
            some code)

            (swap! index inc)
            (recur (nth parts @index))
        )
     )
)

Update:

I also need to use the keywords from parts, inside each if.

niloofar
  • 2,244
  • 5
  • 23
  • 44
  • What are you trying to achieve? What should these `if`s do? `doseq` is just for side effects and returns `nil`, so maybe you need a completely different function/ macro- but that's hard to determine without context. And I would avoid that repeated `if`s using `case`, `cond`, `condp` or something like that. – Martin Půda Apr 10 '23 at 06:44
  • Clojure is not an imperative language; you will have to let go of some of your learned habits and have to embrace functional programming with immutable data. – cfrick Apr 10 '23 at 09:06

3 Answers3

0

how about using nested doseq macros?

(doseq [part [:one :two :three :four]]
   (doseq [each (get my-collection part)]
      ; ...
   ))
erdos
  • 3,135
  • 2
  • 16
  • 27
  • Why should OP use two `doseq`? One `doseq` can iterate over multiple sequences: `(doseq [part [:one :two :three :four] each (get my-collection part)] ...)` – Martin Půda Apr 10 '23 at 06:25
  • @erdos it does not work for me. The page goes blank right after it is loaded after refresh, and everything on the page just appear and disappear so fast, but still no result of the doseq. – niloofar Apr 10 '23 at 06:25
  • @MartinPůda I tried the way you mentioned, but it does not work. The page goes blank after refreshing. – niloofar Apr 10 '23 at 06:29
  • @MartinPůda seems to have forgotten to dereference `my-collection` before betting key. So nothing happens. – leetwinski Apr 10 '23 at 09:13
0

something like this should work.

(def my-collection 
 (atom {:one [:a :b] 
        :two [:c :d] 
        :three [:e :f] 
        :four [:g :h] 
        :five [:aa :bb] 
        :six [:cc :dd] 
        :seven [:ee :ff] 
        :eight [:gg :hh]}))

(doseq [k [:one :two :three :four :five :six :seven :eight]
        item (k @my-collection)]
  ;; replace this one with your business code
  (printf "processing item %s from part %s\n" item k))

;; processing item :b from part :one
;; processing item :c from part :two
;; processing item :d from part :two
;; processing item :e from part :three
;; processing item :f from part :three
;; processing item :g from part :four
;; processing item :h from part :four
;; processing item :aa from part :five
;; processing item :bb from part :five
;; processing item :cc from part :six
;; processing item :dd from part :six
;; processing item :ee from part :seven
;; processing item :ff from part :seven
;; processing item :gg from part :eight
;; processing item :hh from part :eight
leetwinski
  • 17,408
  • 2
  • 18
  • 42
0

Can't really provide exact help without knowing the usecase inside your if blocks. But if iterating over each key-value pair and applying a specific code is your usecase, map would be perfect choice here.

With the following collection:

(def my-collection 
 (atom {:one [1] 
        :two [2] 
        :three [3] 
        :four [4] 
        :five [5] 
        :six [6] 
        :seven [7] 
        :eight [8]}))

You should define your logic as a function, say:

(defn process-kv [[key value]]
    ;; You would probably have a `cond` with specific condition for each key.
    {(name key) (apply list value)})

And map this function over your collection like so:

(map process-kv (seq @my-collection))

This would result in:

({one (1)} 
 {two (2)} 
 {three (3)} 
 {four (4)} 
 {five (5)} 
 {six (6)} 
 {seven (7)} 
 {eight (8)})

You can further ignore processing unknown keys in your collection by adding a keep to your map's output.