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

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

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]))))

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.

Related

How to make reduce more readable in Clojure?

A reduce call has its f argument first. Visually speaking, this is often the biggest part of the form.
e.g.
(reduce
(fn [[longest current] x]
(let [tail (last current)
next-seq (if (or (not tail) (> x tail))
(conj current x)
[x])
new-longest (if (> (count next-seq) (count longest))
next-seq
longest)]
[new-longest next-seq]))
[[][]]
col))
The problem is, the val argument (in this case [[][]]) and col argument come afterward, below, and it's a long way for your eyes to travel to match those with the parameters of f.
It would look more readable to me if it were in this order instead:
(reduceb val col
(fn [x y]
...))
Should I implement this macro, or am I approaching this entirely wrong in the first place?
You certainly shouldn't write that macro, since it is easily written as a function instead. I'm not super keen on writing it as a function, either, though; if you really want to pair the reduce with its last two args, you could write:
(-> (fn [x y]
...)
(reduce init coll))
Personally when I need a large function like this, I find that a comma actually serves as a good visual anchor, and makes it easier to tell that two forms are on that last line:
(reduce (fn [x y]
...)
init, coll)
Better still is usually to not write such a large reduce in the first place. Here you're combining at least two steps into one rather large and difficult step, by trying to find all at once the longest decreasing subsequence. Instead, try splitting the collection up into decreasing subsequences, and then take the largest one.
(defn decreasing-subsequences [xs]
(lazy-seq
(cond (empty? xs) []
(not (next xs)) (list xs)
:else (let [[x & [y :as more]] xs
remainder (decreasing-subsequences more)]
(if (> y x)
(cons [x] remainder)
(cons (cons x (first remainder)) (rest remainder)))))))
Then you can replace your reduce with:
(apply max-key count (decreasing-subsequences xs))
Now, the lazy function is not particularly shorter than your reduce, but it is doing one single thing, which means it can be understood more easily; also, it has a name (giving you a hint as to what it's supposed to do), and it can be reused in contexts where you're looking for some other property based on decreasing subsequences, not just the longest. You can even reuse it more often than that, if you replace the > in (> y x) with a function parameter, allowing you to split up into subsequences based on any predicate. Plus, as mentioned it is lazy, so you can use it in situations where a reduce of any sort would be impossible.
Speaking of ease of understanding, as you can see I misunderstood what your function is supposed to do when reading it. I'll leave as an exercise for you the task of converting this to strictly-increasing subsequences, where it looked to me like you were computing decreasing subsequences.
You don't have to use reduce or recursion to get the descending (or ascending) sequences. Here we are returning all the descending sequences in order from longest to shortest:
(def in [3 2 1 0 -1 2 7 6 7 6 5 4 3 2])
(defn descending-sequences [xs]
(->> xs
(partition 2 1)
(map (juxt (fn [[x y]] (> x y)) identity))
(partition-by first)
(filter ffirst)
(map #(let [xs' (mapcat second %)]
(take-nth 2 (cons (first xs') xs'))))
(sort-by (comp - count))))
(descending-sequences in)
;;=> ((7 6 5 4 3 2) (3 2 1 0 -1) (7 6))
(partition 2 1) gives every possible comparison and partition-by allows you to mark out the runs of continuous decreases. At this point you can already see the answer and the rest of the code is removing the baggage that is no longer needed.
If you want the ascending sequences instead then you only need to change the < to a >:
;;=> ((-1 2 7) (6 7))
If, as in the question, you only want the longest sequence then put a first as the last function call in the thread last macro. Alternatively replace the sort-by with:
(apply max-key count)
For maximum readability you can name the operations:
(defn greatest-continuous [op xs]
(let [op-pair? (fn [[x y]] (op x y))
take-every-second #(take-nth 2 (cons (first %) %))
make-canonical #(take-every-second (apply concat %))]
(->> xs
(partition 2 1)
(partition-by op-pair?)
(filter (comp op-pair? first))
(map make-canonical)
(apply max-key count))))
I feel your pain...they can be hard to read.
I see 2 possible improvements. The simplest is to write a wrapper similar to the Plumatic Plumbing defnk style:
(fnk-reduce { :fn (fn [state val] ... <new state value>)
:init []
:coll some-collection } )
so the function call has a single map arg, where each of the 3 pieces is labelled & can come in any order in the map literal.
Another possibility is to just extract the reducing fn and give it a name. This can be either internal or external to the code expression containing the reduce:
(let [glommer (fn [state value] (into state value)) ]
(reduce glommer #{} some-coll))
or possibly
(defn glommer [state value] (into state value))
(reduce glommer #{} some-coll))
As always, anything that increases clarity is preferred. If you haven't noticed already, I'm a big fan of Martin Fowler's idea of Introduce Explaining Variable refactoring. :)
I will apologize in advance for posting a longer solution to something where you wanted more brevity/clarity.
We are in the new age of clojure transducers and it appears a bit that your solution was passing the "longest" and "current" forward for record-keeping. Rather than passing that state forward, a stateful transducer would do the trick.
(def longest-decreasing
(fn [rf]
(let [longest (volatile! [])
current (volatile! [])
tail (volatile! nil)]
(fn
([] (rf))
([result] (transduce identity rf result))
([result x] (do (if (or (nil? #tail) (< x #tail))
(if (> (count (vswap! current conj (vreset! tail x)))
(count #longest))
(vreset! longest #current))
(vreset! current [(vreset! tail x)]))
#longest)))))))
Before you dismiss this approach, realize that it just gives you the right answer and you can do some different things with it:
(def coll [2 1 10 9 8 40])
(transduce longest-decreasing conj coll) ;; => [10 9 8]
(transduce longest-decreasing + coll) ;; => 27
(reductions (longest-decreasing conj) [] coll) ;; => ([] [2] [2 1] [2 1] [2 1] [10 9 8] [10 9 8])
Again, I know that this may appear longer but the potential to compose this with other transducers might be worth the effort (not sure if my airity 1 breaks that??)
I believe that iterate can be a more readable substitute for reduce. For example here is the iteratee function that iterate will use to solve this problem:
(defn step-state-hof [op]
(fn [{:keys [unprocessed current answer]}]
(let [[x y & more] unprocessed]
(let [next-current (if (op x y)
(conj current y)
[y])
next-answer (if (> (count next-current) (count answer))
next-current
answer)]
{:unprocessed (cons y more)
:current next-current
:answer next-answer}))))
current is built up until it becomes longer than answer, in which case a new answer is created. Whenever the condition op is not satisfied we start again building up a new current.
iterate itself returns an infinite sequence, so needs to be stopped when the iteratee has been called the right number of times:
(def in [3 2 1 0 -1 2 7 6 7 6 5 4 3 2])
(->> (iterate (step-state-hof >) {:unprocessed (rest in)
:current (vec (take 1 in))})
(drop (- (count in) 2))
first
:answer)
;;=> [7 6 5 4 3 2]
Often you would use a drop-while or take-while to short circuit just when the answer has been obtained. We could so that here however there is no short circuiting required as we know in advance that the inner function of step-state-hof needs to be called (- (count in) 1) times. That is one less than the count because it is processing two elements at a time. Note that first is forcing the final call.
I wanted this order for the form:
reduce
val, col
f
I was able to figure out that this technically satisfies my requirements:
> (apply reduce
(->>
[0 [1 2 3 4]]
(cons
(fn [acc x]
(+ acc x)))))
10
But it's not the easiest thing to read.
This looks much simpler:
> (defn reduce< [val col f]
(reduce f val col))
nil
> (reduce< 0 [1 2 3 4]
(fn [acc x]
(+ acc x)))
10
(< is shorthand for "parameters are rotated left"). Using reduce<, I can see what's being passed to f by the time my eyes get to the f argument, so I can just focus on reading the f implementation (which may get pretty long). Additionally, if f does get long, I no longer have to visually check the indentation of the val and col arguments to determine that they belong to the reduce symbol way farther up. I personally think this is more readable than binding f to a symbol before calling reduce, especially since fn can still accept a name for clarity.
This is a general solution, but the other answers here provide many good alternative ways to solve the specific problem I gave as an example.

Clojure: Executing an operation n times using the output as input of next operation (a-la reduce)

I want to execute a given amount of time a certain operation (e.g., generating a tribe). Each time I would like to use the output of the previous iteration as input of the next one.
I am achieving it by doing a dummy reduce on collection of n elements, I then consider only the accumulator and throw away the element from the collection.
(defn generate-game [world n-tribes]
(let [ game (create-game world)
game (reduce (fn [acc, _] (:game (generate-tribe acc))) game (repeat n-tribes :just_something))]
game))
I assume there is a much better way to do that. Can you help me finding it?
If it's the same function repeated n-tribes times, then using iterate and getting the n-tribes'th element should work:
(defn generate-game [world n-tribes]
(let [ game (create-game world)
game (nth (iterate generate-tribe game) n-tribes)]
game))
Remember that iterate creates a lazy sequence so nothing will be calculated until you request it.
Another option is applying comp to the list of functions, after all it's a simple function composition:
(generate-tribe (generate-tribe .... (generate-tribe game) ....))
n-tribes times
So something like:
(defn generate-game [world n-tribes]
(let [ game (create-game world)
game ((apply comp (repeat n-tribes generate-tribe)) game)]
game))
expresses exactly that idea.
Not a Clojure expert, but I would expect
(defn generate-game [world n-tribes]
(nth (iterate generate-tribe (create-game world)) n-tribes))
or (less terse)
(defn generate-game [world n-tribes]
(let [game (create-game world)]
(nth (iterate generate-tribe game) n-tribes)))
to work
The method used in the question is fine, but use range instead
(defn generate-game [world n-tribes]
(reduce (fn [acc _] (:game (generate-tribe acc)))
(create-game world)
(range n-tribes)))
Since range objects know how to intelligently reduce themselves, this will get turned into a loop. This is the reduce method of range:
public Object reduce(IFn f, Object start) {
Object ret = f.invoke(start,n);
for(int x = n+1;x < end;x++)
ret = f.invoke(ret, x);
return ret;
}
If your game state is going to wind up in an atom anyway then you could also consider dotimes to update it.
(defn generate-game [world n-tribes]
(let [game (atom (create-game world))]
(dotimes [_ n-tribes] (swap! game (comp :game generate-tribe)))
game))
Iterate is also a fine solution. More discussion at Iteratively apply function to its result without generating a seq.

Pass multiple parameters function from other function with Clojure and readability issues

I'm trying to learn functional programming with SICP. I want to use Clojure.
Clojure is a dialect of Lisp but I'm very unfamiliar with Lisp. This code snippet unclean and unreadable. How to write more efficient code with Lisp dialects ?
And how to pass multiple parameters function from other function ?
(defn greater [x y z]
(if (and (>= x y) (>= x z))
(if (>= y z)
[x,y]
[x,z])
(if (and (>= y x) (>= y z))
(if (>= x z)
[y,x]
[y,z])
(if (and (>= z x) (>= z y))
(if (>= y x)
[z,y]
[z,x])))))
(defn sum-of-squares [x y]
(+ (* x x) (* y y)))
(defn -main
[& args]
(def greats (greater 2 3 4))
(def sum (sum-of-squares greats)))
You are asking two questions, and I will try to answer them in reverse order.
Applying Collections as Arguments
To use a collection as an function argument, where each item is a positional argument to the function, you would use the apply function.
(apply sum-of-squares greats) ;; => 25
Readability
As for the more general question of readability:
You can gain readability by generalizing the problem. From your code sample, it looks like the problem consists of performing the sum, of the squares, on the two largest numbers in a collection. So, it would be visually cleaner to sort the collection in descending order and take the first two items.
(defn greater [& numbers]
(take 2 (sort > numbers)))
(defn sum-of-squares [x y]
(+ (* x x) (* y y)))
You can then use apply to pass them to your sum-of-squares function.
(apply sum-of-squares (greater 2 3 4)) ;; => 25
Keep in Mind: The sort function is not lazy. So, it will both realize and sort the entire collection you give it. This could have performance implications in some scenarios. But, in this case, it is not an issue.
One Step Further
You can further generalize your sum-of-squares function to handle multiple arguments by switching the two arguments, x and y, to a collection.
(defn sum-of-squares [& xs]
(reduce + (map #(* % %) xs)))
The above function creates an anonymous function, using the #() short hand syntax, to square a number. That function is then lazily mapped, using map, over every item in the xs collection. So, [1 2 3] would become (1 4 9). The reduce function takes each item and applies the + function to it and the current total, thus producing the sum of the collection. (Because + takes multiple parameters, in this case you could also use apply.)
If put it all together using one of the threading macros, ->>, it starts looking very approachable. (Although, an argument could be made that, in this case, I have traded some composability for more readability.)
(defn super-sum-of-squares [n numbers]
(->> (sort > numbers)
(take n)
(map #(* % %))
(reduce +)))
(super-sum-of-squares 2 [2 3 4]) ;;=> 25
(defn greater [& args] (take 2 (sort > args)))
(defn -main
[& args]
(let [greats (greater 2 3 4)
sum (apply sum-of-squares greats)]
sum))
A key to good clojure style is to use the built in sequence operations. An alternate approach would have been a single cond form instead of the deeply nested if statements.
def should not be used inside function bodies.
A function should return a usable result (the value returned by -main will be printed if you run the project).
apply uses a list as the args for the function provided.
To write readable code, use the functions provided by the language as much as possible:
e.g. greater can be defined as
(defn greater [& args]
(butlast (sort > args)))
To make sum-of-squares work on the return value from greater, use argument destructuring
(defn sum-of-squares [[x y]]
(+ (* x x) (* y y)))
which requires the number of elements in the argument sequence to be known,
or define sum-of-squares to take a single sequence as argument
(defn sum-of-squares [args]
(reduce + (map (fn [x] (* x x)) args)))

Clojure Partial Application - How to get 'map' to return a collection of functions?

I have a function that I basically yanked from a discussion in the Clojure google group, that takes a collection and a list of functions of arbitrary length, and filters it to return a new collection containing all elements of the original list for which at least one of the functions evaluates to true:
(defn multi-any-filter [coll & funcs]
(filter #(some true? ((apply juxt funcs) %)) coll))
I'm playing around with making a generalizable solution to Project Euler Problem 1, so I'm using it like this:
(def f3 (fn [x] (= 0 (mod x 3))))
(def f5 (fn [x] (= 0 (mod x 5))))
(reduce + (multi-any-filter (range 1 1000) f3 f5))
Which gives the correct answer.
However, I want to modify it so I can pass ints to it instead of functions, like
(reduce + (multi-any-filter (range 1 1000) 3 5))
where I can replace 3 and 5 with an arbitrary number of ints and do the function wrapping of (=0 (mod x y)) as an anonymous function inside the multi-any-filter function.
Unfortunately this is past the limit of my Clojure ability. I'm thinking that I would need to do something with map to the list of args, but I'm not sure how to get map to return a list of functions, each of which is waiting for another argument. Clojure doesn't seem to support currying the way I learned how to do it in other functional languages. Perhaps I need to use partial in the right spot, but I'm not quite sure how.
In other words, I want to be able to pass an arbitrary number of arguments (that are not functions) and then have each of those arguments get wrapped in the same function, and then that list of functions gets passed to juxt in place of funcs in my multi-any-filter function above.
Thanks for any tips!
(defn evenly-divisible? [x y]
(zero? (mod x y)))
(defn multi-any-filter [col & nums]
(let [partials (map #(fn [x] (evenly-divisible? x %)) nums)
f (apply juxt partials)]
(filter #(some true? (f %)) col)))
I coudn't use partial because it applies the arg in the first position of the fn. We want it in the second position of evenly-divisible? We could re-arrange in evenly-divisible? but then it would not really look correct when using it standalone.
user=> (reduce + (multi-any-filter (range 1 1000) 3 5))
233168

Partial out all but i-th variable in variadic function in Clojure

I'm starting out learning Clojure, and was trying to implement some basic numerical derivative functions for practice. I'm trying to create a gradient function that accepts an n-variable function and the points at which to evaluate it. To do this in a "functional" style, I want to implement the gradient as a map of a 1-variable derivatives.
The 1-variable derivative function is simple:
(defn derivative
"Numerical derivative of a univariate function."
[f x]
(let [eps 10e-6] ; Fix epsilon, just for starters.
; Centered derivative is [f(x+e) - f(x-e)] / (2e)
(/ (- (f (+ x eps)) (f (- x eps))) (* 2 eps))))
I'd like to design the gradient along these lines:
(defn gradient
"Numerical gradient of a multivariate function."
[f & x]
(let [varity-index (range (count x))
univariate-in-i (fn [i] (_?_))] ; Creates a univariate fn
; of x_i (other x's fixed)
;; For each i = 0, ... n-1:
;; (1) Get univariate function of x_i
;; (2) Take derivative of that function
;; Gradient is sequence of those univariate derivatives.
(map derivative (map univariate-in-i varity-index) x)))
So, gradient has variable arity (can accept any # of x's), and the order of the x's counts. The function univariate-in-i takes an index i = 0, 1, ... n-1 and returns a 1-variable function by partial-ing out all the variables except x_i. E.g., you'd get:
#(f x_0 x_1 ... x_i-1 % x_i+1 ... x_n)
^
(x_i still variable)
map-ping this function over varity-index gets you a sequence of 1-variable functions in each x_i, and then map-ping derivative over these gets you a sequence of derivatives in each x_i which is the gradient we want.
My questions is: I'm not sure what a good way to implement univariate-in-i is. I essentially need to fill in values for x's in f except at some particular spot (i.e., place the % above), but programmatically.
I'm more interested in technique than solution (i.e., I know how to compute gradients, I'm trying to learn functional programming and idiomatic Clojure). Therefore, I'd like to stay true to the strategy of treating the gradient as a map of 1-d derivatives over partialed-out functions. But if there's a better "functional" approach to this, please let me know. I'd rather not resort to macros if possible.
Thanks in advance!
Update:
Using Ankur's answer below, the gradient function I get is:
(defn gradient
"Numerical gradient of a multivariate function."
[f & x]
(let [varity-index (range (count x))
x-vec (vec x)
univariate-in-i
(fn [i] #(->> (assoc x-vec i %) (apply f)))]
(map derivative (map univariate-in-i varity-index) x)))
which does exactly what I'd hoped, and seems very concise and functional.
You can define univariate-in-i as shown below. (Assuming that all the other position values are defined in some var default which is a vector)
(fn [i] #(->>
(assoc default i %)
(apply f)))
if you find this abit difficult to comprehend (in the context of how to implement gradient), another variant of multivariable gradient implementation using clojure:
then, given f and vector v of a1,....,aN, will differentiate while all the variables except xi are fixed:
(defn partial-diff [f v i]
(let [h 10e-6
w (update v i + h)]
(/ (- (apply f w) (apply f v))
h)))
(defn gradient [f v]
(map #(partial-diff f v %) (range (count v))))
=>
(gradient (fn [x y]
(+ (* x x) (* x y y))) [3 3])
=> (15.000009999965867 18.000030000564493)