You could start with pure functions to handle the game logic, e.g.: (defn new-game [] [[\- \- \-] [\- \- \-] [\- \- \-]])
(defn print-game [game] (doseq [row game] (println (apply str row)))) (defn move [game mark pos] (assoc-in game pos mark)) (print-game (new-game)) (print-game (move (new-game) \x [1 1])) (print-game (-> (new-game) (move \x [1 1]) (move \o [0 2]))) On Friday, April 20, 2012 3:30:59 PM UTC+2, Craig Ching wrote: > > Thanks for the help to both of you! Question, does it seem heavy handed > to do it this way? I mean, atoms are more for thread-safety, aren't they? > I don't have threads so it seems a bit much to use atoms for this. Am I > better off using recur and trying to loop? Or is this considered an > idiomatic way to handle mutable data in Clojure? I always found wrapping > up mutable data in a closure as we did in Scheme to be pretty elegant, but > maybe something like that goes against the desire of Clojure to protect > against concurrent modification, is that about right? > > Thanks again! > > On Thursday, April 19, 2012 10:01:23 PM UTC-5, Gaz wrote: >> >> to answer your question directly, you would need to do something like >> this to make it work the way your example is set up: >> >> (defn new-game [] >> (let [board (atom (into [] (repeat 9 nil)))] >> (fn [n & [i]] >> (cond >> (= n :x) (swap! board assoc i 'x) >> (= n :o) (swap! board assoc i 'o) >> (= n :print) (println @board))))) >> >> (def g1 (new-game)) >> >> (g1 :x 0) >> (g1 :print) >> >> On Thu, Apr 19, 2012 at 9:58 PM, Armando Blancas <abm221...@gmail.com> >> wrote: >> > You could keep the board in an atom so it can mutate; then try to find >> maybe >> > two good places for mutation to happen, your move and the program's. >> With >> > the rest being functional you'll avoid the problems of global state >> while >> > not being forced to fit your logic into a loop of some re-binding that >> > simulates mutation. >> > >> > >> > On Thursday, April 19, 2012 3:21:56 PM UTC-7, Craig Ching wrote: >> >> >> >> Ok, I've read that what I want to do is a no no. But this is the sort >> of >> >> thing I did in Scheme about 20 years ago (and because of that I'm >> probably >> >> misremembering ;-)). >> >> >> >> Basically I'm learning clojure and thought I'd write a tic tac toe >> game. >> >> But not any tic tac toe, I want to write one where I can have multiple >> >> games going simultaneously. Something like: >> >> >> >> (def g1 (new-game)) >> >> (def g2 (new-game)) >> >> >> >> (g1 :x 0) >> >> (g1 :print) >> >> (g2 :x 5) >> >> (g2 :print) >> >> >> >> So the schemer in me (and probably the imperative programmer as well) >> >> thought I could return a clojure that encapsulates the board value, >> >> something like this: >> >> >> >> (defn new-game [] >> >> >> >> (let [board (into [] (repeat 9 nil))] >> >> >> >> (fn [n i] >> >> >> >> (cond >> >> >> >> (= n :x)(set! board (assoc board i 'x)) >> >> >> >> (= n :o)(set! board (assoc board i 'o)) >> >> >> >> (= n :print) (println board))))) >> >> >> >> >> >> Of course I get an error saying I can't bind to the non-mutable board. >> >> >> >> I'm really new to Clojure, so apologies if this is really basic for >> this >> >> list. Can I do what I want or can someone point me in the right >> direction? >> >> I've seen some other tic tac toe implementations on github, but they >> use >> >> recur to track state and I was hoping there was a cleaner idiomatic >> way than >> >> that. >> >> >> >> Thanks! >> >> >> > -- >> > 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 >> >> -- 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