Combining thread-last with loop in clojure

Viewed 56

I write small card game and i want my code to be very explicit and therefore make it clear on a high level, that there are rounds to play. My first implementation was:

(defn play-game []
  (->
   (myio/initialize-cards-and-players)
   (shuffle-and-share-cards myio/myshuffle)
   ;(announce)
   (play-rounds)
  )
)

I want the play rounds to be more explicit and show, that it is a loop on top-level:

(defn play-game []


  (->>
   (myio/initialize-cards-and-players)
   (shuffle-and-share-cards myio/myshuffle)
   (announce)

   (loop [round 1]
     (play-round-with-game round)
     (if (<= round 4)
       (recur (+ round 1))
       )
     )
                                        ;   (play-round-with-game 2)
                                        ;   (play-round-with-game 3)
                                        ;   (play-round-with-game 4)


   )
  )

But i somehow cannot get the "game" object, that is returned by every function into the loop. Is there a good way to handle this with thread-last?

Or is there a way to use reduce instead of the loop?

1 Answers

As Eugene suggested, you want to keep it simple. The following is the structure I normally use

(defn play-game
  []
  (let [game-init (->>
                    (myio/initialize-cards-and-players)
                    (shuffle-and-share-cards myio/myshuffle)
                    (announce))]
    (loop [round 1
           game  game-init]
      (if (< 4 round)
        game ; return result
        (let [game-next (play-round-with-game game round)]
          (recur (inc round) game-next))))))

I like to use let forms to give each value an explicit name. It helps to avoid confusion, especially for new readers of the code. If the (inc round) was not so simple, I would also make an explicit round-next variable and use that in the recur.

Also, I like the return condition to be the first thing checked in each iteration of the loop. This normally leaves the recur as the last statement in the loop.

Related