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)))))
Related
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)
I'm new to clojure and tried to implement the some function (for some specific tests):
(my-some even? [1 2 3 4]) => true
(my-some #{3 4} [1 2 3 4]) => 3
(my-some zero? [1 2 3 4]) => nil
That's what I came up with so far:
(defn my-some [f x]
(loop [[y & t] x]
(if (empty? t) nil
(if (f y)
(f y)
(recur t)))))
I could imagine there are more idiomatic approaches.
Any suggestions?
Firstly, you have a bug: [[y & t] x] destructures x, but the following empty? check on t means you are ignoring the last element in the sequence. You can see this with
(my-some even? [2])
=> nil
You can replace (if (empty? x) nil (else-form)) with when and seq:
(when (seq x) ...)
you can then use first and next to deconstruct the sequence:
(defn my-some [f x]
(when (seq x)
(if (f (first x))
(f (first x))
(recur f (rest x)))))
the call to recur is then back into my-some so you need to pass the predicate f.
you can replace (if x x (else ....)) with (or x (else ...)):
(defn my-some [f x]
(when (seq x)
(or (f (first x)) (recur f (next x)))))
you can compare this with the implementation of some
this code:
(vector (first x)
(for [i (range (dec (count x)))] (+ (nth x i) (nth x (inc i))))
(last x)
)
will return [1 (2) 1] for x=[1 1]. How I can make [1 2 1] instead [1 (2) 1] in best practice?
A simpler way to do what you want:
(concat [(first x)] (map + x (rest x)) [(last x)])
or if it must be a vector:
(into [(first x)] (conj (mapv + x (rest x)) (last x)))
As a convenient shorthand equivalent to Diego's answer, I would usually use a syntax-quoted expression here:
`[~(first x)
~#(map + x (rest x))
~(last x)]
An even more bulletproof solution is:
(flatten [ (first x)
(map + x (rest x))
(last x) ] )
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)))
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)