Hi Michael, Larry recently posted something similar http://groups.google.com/group/clojure/browse_thread/thread/773e628953b40d9f Which generated also quite a lot of discussion which you might also be interested in.
> (def matrix #{[-1 -1] [-1 0] [-1 1] [0 -1] [0 0] [0 1] [1 -1] [1 0] [1 1]}) > (defn neighbours > "All direct neighbours around [pos] and pos itself" > [pos] > (defn translate [[x y]] [(+ x (first pos)) (+ y (second pos))]) > (map translate matrix) > ) Nothing wrong with it, but using def or defn inside a defn exposes a new global var. In this case 'translate' is now a global function which will have values relative to the last time neighbours was called. You could make it locally scoped by doing something like: (let [matrix #{.....}] (defn neighbours "All direct neighbours around [pos] and pos itself" [pos] (let [translate (fn [[x y]] ......)] (map translate matrix)))) This is not really any nicer I'm only bringing it up to make sure you are aware of the scoping implications of using defn (or def) inside a function. You can write an equivalent function without using matrix or translate: (defn neighbours "All direct neighbours around [pos] and pos itself" [[x y]] (for [dx [-1 0 1] dy [-1 0 1]] [(+ x dx) (+ y dy)])) > new-board (map > (fn [[x y]] (if (alive [x y] board) [x y] nil)) > (all-neighbours bsize board)) > ] It might have been more convenient to define alive such that instead of returning a boolean, it returns pos or nil. Then you could avoid wrapping it in an anonymous function and just do (map alive (all-neighbours bsize board)) > (set (filter #(not (nil? %)) new-board)))) You can use the 'identity' function instead of not nil? to be more concise: user=> (filter identity [1 nil 2]) (1 2) > (defn to-string > "creates a string representation of a board" > ([board] (to-string size board)) > ([bsize board] > (def axis (range bsize)) > (reduce > (fn [text x] > (str text (reduce > (fn [text y] > (str text (if (contains? board [x y]) "#" "_")) > ) > "" axis) > "\n")) "" axis))) ; untested but I think you could write this along the lines of: (str (for [i (range bsize)] (concat \newline (for [j (range bsize)] (if (contains? board [i j]) "#" "_")))) > (defn demo > "runs a simple board 10 times" > [] > (map > #(println (to-string %)) > (take 10 (iterate next-board start-board)) > )) map creates a lazy sequence. for side-effects to be realized the sequence needs to be forced. This can be a bit of a trap if you are expecting side-effects (like printing) but they never occur. Consider using doseq instead of map in such a scenario: (doseq [b (take 10 (iterate next-board start-board))] (println (to-string b))) Regards, Tim. --~--~---------~--~----~------------~-------~--~----~ 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 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 -~----------~----~----~----~------~----~------~--~---