Can you pass the data to the next iteration in (for ...)?

I am working on learning clojure after work, and I am doing this by creating a small game (loving the quil library) to introduce me to the various aspects of clojure in specific and FP in general.

So, my game world exists from a three-dimensional grid of structural map data (vector of vector of map vector). I want to repeat every point in 3D space (map) and change the data when the condition is met. This was my initial decision:

(game data structure - game state (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 xyz :type] :soil)))) 

But this returns a list of results (game state data structure) of each iteration instead of one game data structure. I should somehow easily pass the result of each iteration. Something like loop / recur, probably, but I think you cannot combine recur with for.

Someone tell me?

thanks

+6
source share
2 answers

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 [xyz]] (assoc-in g [:world xyz :type] :soil))) game (for [x (range world-x) y (range world-y) z (range world-z) :when (> z (* world-z (rand)))] [xyz])))) 
+8
source

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 usually very useful when there is a concept of "accumulated value" in functional programming. The advantage in this is also very effective.

+2
source

All Articles