I'm working on a turn-based game and I'm looking for a good way to manage states. In the game each turn is composed of multiple phases. I started by using atoms for the phases field (this is a sequence of functions) in a record and realized that it wouldn't be ideal to keep track of states in the case where I'd need to keep a snapshot of every phases. Here's the original code I had:
(defrecord Game [phases] (next-phase [this] (stop-timer) (swap! phases #(conj (vec (rest %)) (first %))) (log :info "change phase to %s" (key (first @phases))) (start-phase this)) I then started to think that this would be a good opportunity to use a state monad. I've tried to reimplement the above code using the algo.monads library but the result was less than satisfactory (probably due to my own shortcoming), here's the monadic version: (defrecord Game [phases] (next-phase [this] (-> ((domonad state-m [_ (fn [s] (stop-timer) [s s]) _ (update-state (fn [s] (update-in s [:phases] #(conj (vec (rest %)) (first %))))) _ (fn [s] (log :info "change phase to %s" (key (first (:phases s)))) [s s])] nil) state) second start-phase)) As my code probably doesn't need the full power of the state monad, I tried to write a lighter-weight version using the following macro: (defmacro >> [& state-and-forms] (reduce #(list (if ('#{fn fn*} (first %2)) %2 `(fn [s#] ~%2 s#)) %) state-and-forms)) Which let me write: (next-phase [state] (>> state (stop-timer) (fn [s] (update-in s [:phases] #(conj (vec (rest %)) (first %)))) #(do (log :info "change phase to %s" (key (first (:phases %)))) %) #(start-phase %))) With some more helper macro this version looks promising. In the end I wonder if there's some Clojure feature I'm overlooking or if I should rethink the whole solution? Is there a better way to accomplish this? -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en