Loop destructuring in Clojure - clojure

Is there a way for destructuring the recur bindings in a loop?
So for example if i want to let y stay unchanged in
(loop [x 1 y 1] (if (< x 5) (recur (inc x) _ ) (println "result:" x y))
I know this is not possible, but how could i get a similar thing like _ in sequential destructuring for recur?

Assuming y never changes inside the loop, you can just wrap everything in a let that binds a value to y, or even place your loop in a function that receives y as an argument.
let
(let [y 1]
(loop [x 1]
(if (< x 5)
(recur (inc x))
(println "result:" x y)))
defn
(defn loop-with [y]
(loop [x 1]
(if (< x 5)
(recur (inc x))
(println "result:" x y)))

Related

Why is this function not evaluating

I have been stuck on this one for a while and cant figure it out. Why is the function not evaluating for values greater or equal than 2? It works fine for values under it but anything above and it just prints the output seen in the pic
((fn fib
([x] (cond
(zero? x) []
(= x 1) [1]
(>= x 2) fib (- x 2) [1 1]))
([x seq] (if (zero? x)
seq
(recur (dec x) (conj seq (+ (last seq) (nth seq (- (count seq) 2)))))))) 3)
enter image description here
You forgot one parenthesis on this line, before fib:
(>= x 2) fib (- x 2) [1 1]))
After you will add it, this code will work. Just note that your variables shouldn't have the same name as already existing functions- you were shadowing core function seq.
((fn fib
([x] (cond
(zero? x) []
(= x 1) [1]
(>= x 2) (fib (- x 2) [1 1])))
([x values]
(if (zero? x)
values
(recur (dec x)
(conj values (+ (last values)
(nth values (- (count values) 2)))))))) 3)

Iterate help in Clojure

I'm new to Clojure and am trying to write a Newton's method function using the built in iterate. I have tried several things that resulted in the following code. Any ideas as to why this is only returning empty parens? I'm open to new ideas as well.
(defn within-tol?
"returns true if the guess is within the given tolerance"
[guess x tolerance]
(< (abs (- (square guess) x)) tolerance))
(defn next-guess
[guess x]
(average guess (/ x guess)))
(defn average
[x y]
(float (/ (+ x y) 2)))
(defn abs
[x]
(cond
(< x 0) (- x)
:else x))
(defn square
[x]
(* x x))
(defn sqrt-iter
[guess x tolerance]
(if (within-tol? guess x tolerance) guess
(sqrt-iter (next-guess guess x) x tolerance)))
(defn sqrt
[guess x tolerance]
(take-while #(within-tol? % x tolerance) (iterate #((sqrt % x tolerance)) guess)))
Seems your sqrt is wrong as it does not use next-guess
Try that
(defn sqrt
[guess x tolerance]
(first (drop-while #(not (within-tol? % x tolerance))
(iterate #(next-guess % x) guess))))
Example:
(sqrt 1 169 0.01) => 13.0

how would a loop with a nested return be implemented in clojure?

I'm playing around with a crafty tutorial here:
http://buildnewgames.com/introduction-to-crafty/
and am wondering how this particular function be implemented in clojurescript/clojure
var max_villages = 5;
for (var x = 0; x < Game.map_grid.width; x++) {
for (var y = 0; y < Game.map_grid.height; y++) {
if (Math.random() < 0.02) {
Crafty.e('Village').at(x, y);
if (Crafty('Village').length >= max_villages) {
return;
}
}
}
}
I know that we can have the (for []) construct but how would you get it to stop when max_villages hits 5?
Here's one approach:
(def max-villages 5)
(->> (for [x (range map-width)
y (range map-height)]
[x y])
(filter (fn [_] (< (rand) 0.02)))
(take max-villages))
Then perhaps add (map make-village-at) or something similar as the next stage of the pipeline; if it's meant to perform side effects, add a dorun or doall as the final stage to force them to happen at once (choosing one or the other depending on whether the return values are interesting).
NB. some extra vectors and random numbers may be generated due to seq chunking, it'll be less than 32 though.
A more imperative approach with a counter for comparison:
(let [counter (atom 0)]
(doseq [x (range map-width)
:while (< #counter max-villages)
y (range map-height)
:while (< #counter max-villages)
:when (< (rand) 0.02)]
(swap! counter inc)
(prn [x y]))) ; call make-village-at here
:while terminates the loop at the current nesting level when its test expression fails; :when moves on to the next iteration immediately. doseq supports chunking too, but :while will prevent it from performing unnecessary work.
Using recursion it would be something like:
(letfn [(op [x y]
(if (= (rand) 0.02)
(do
(village-at x y)
(if (>= (village-length) max-villages) true))))]
(loop [x 0 y 0]
(when (and (< x width) (not (op x y)))
(if (= (inc y) height)
(recur (inc x) 0)
(recur x (inc y))))))
That's a great tutorial!
A variation on Michael's approach (I would have just commented to his answer but I don't have enough stack power yet) would be to use Cartesian products rather than nested for loops:
;; some stub stuff to get the example to run
(ns example.core
(:use clojure.math.combinatorics))
(def max-villages 5)
(def map-width 10)
(def map-height 10)
(defn crafty-e [x y z] (print z))
;; the example, note I use doseq rather than map to empasize the fact that the loop
;; is being performed for its side effects not its return value.
(doseq [coord (take max-villages
(filter
(fn [_] (< (rand) 0.02))
(cartesian-product (range map-width) (range map-height))))]
(crafty-e :village :at coord))

Returning a value from a loop

Is there anyway i can return a value from a loop since the recursion has to be at the tail
(ns for)
(defn abc [y]
(loop [x 10]
(when (> x 2)
(if (= 2 3) (do (println "test") (recur (- x 2)))
(do (let [x (+ 1 x)
y 2] (println y) (recur (- x 2))))))))
(abc 1)
is there anyway i can return a value for the function by taking y as a parameter and updating a new value of y. However, the recur part has to be at the last line of the code hence i am unable to put y as the last line of the code.
Example
(ns for)
(defn abc [y]
(loop [x 10]
(when (> x 2)
(if (= 2 3) (do (println "test") (recur (- x 2)))
(do (let [x (+ 1 x)
y 2] (println y) (recur (- x 2)))))))
y)
(abc 1)
This would give me an error since recur has to be the last line of code. I have looked at similar questions and it says to put the return value at the end of the if loop which i tried but failed which gives me an exception thatthe recursion can only happen at the tail
I guess you meant this:
(defn abc [y]
(loop [x 10
y nil]
(if (> x 2)
(if (= 2 3)
(do (println "test")
(recur (- x 2) nil))
(do (let [x (+ 1 x)
y 2]
(println y)
(recur (- x 2) y))))
y)))
Update. Without unnecessary parts it would be
(defn abc [y]
(loop [x 10]
(if (> x 2)
(do (println 2)
(recur (- x 1)))
2)))
which is the same as
(defn abc [_]
(dotimes [_ 8] (println 2))
2)

recursion in clojure

I am trying to make this sample program work
(defn foo
([x] (foo x []))
([x current]
(when (> x 0)
(recur (dec x) (conj current x)))))
When I call this function (foo 5), I should get [1 2 3 4 5], however it only returns nil. What am I doing wrong?
Thanks,
Murtaza
Your recursion doesn't have a return expression i.e when then when is false the recursion terminates and it returns nil. You can fix this using if as:
(defn foo
([x] (foo x []))
([x current]
(if (> x 0)
(recur (dec x) (conj current x))
current)))
This will return [5 4 3 2 1] for (foo 5) as you are using vector as return value and conj on vector appends the item at the end of the vector. You can either reverse the vector or use list i.e in place of (foo x []) use (foo x '())
The code below works. I was not returning the final value.
(defn foo
([x] (foo x []))
([x current]
(if (> x 0)
(recur (dec x) (conj current x))
current)))
I have corrected your original program to use (if (= x 0) instead of (when (> x 0), and this returns [1 2 3 4 5].
(defn foo
([x] (foo x []))
([x current]
(if (= x 0)
(apply vector (sort < current))
(recur (dec x) (conj current x)))))