6
votes

I am in the progress of learning clojure after work and I'm doing this by making a small game (loving the quil library) to make me familiar with the different aspects of clojure in specific and FP in general.

So, my game world exists of 3d grid of map data strucutures (vector of a vector of a vector of a map). I want to itterate over every point in 3d space (map) and change the data when a condition is met. This was my initial solution:

(the game data structure is the game state (a map))

(defn soil-gen [game]
  (let [world-x (game :world-x)
        world-y (game :world-y)
    world-z (game :world-z)]
      (for [x (range world-x) 
          y (range world-y) 
          z (range world-z) 
          :when (> z (* world-z (rand)))]
         (assoc-in game [:world x y z :type] :soil))))

But this returns a list of the results (my game state data structure) of every iteration instead of one game data structure. I should somehow be able to pass the result of each iteration back to for. Something like loop/recur probably but I think you cant combine recur with for.

Somebody a clue?

thanks

2

2 Answers

8
votes

What you can do is use reduce with for as shown below:

(defn soil-gen [game]
  (let [world-x (game :world-x)
        world-y (game :world-y)
    world-z (game :world-z)]

    (reduce (fn [g [x y z]] (assoc-in g [:world x y z :type] :soil)))
            game
            (for [x (range world-x) 
                  y (range world-y) 
                  z (range world-z) 
                 :when (> z (* world-z (rand)))]
                 [x y z]))))
2
votes

You probably want to use something like reduce to pass the accumulated result between each iteration.

Simplified examples:

(reduce 
  (fn [m val] (assoc m val (str "foo" val))) 
  {}               ;; initial value for m 
  (range 5))       ;; seqence of items to reduce over

=> {4 "foo4", 3 "foo3", 2 "foo2", 1 "foo1", 0 "foo0"}

reduce is generally very useful whenever so have some concept of an "accumulated value" in functional programming. It also has the advantage of being very efficient.