Recursively reverse a sequence in Clojure - recursion

I want to reverse a sequence in Clojure without using the reverse function, and do so recursively.
Here is what I came up with:
(defn reverse-recursively [coll]
(loop [r (rest coll)
acc (conj () (first coll))]
(if (= (count r) 0)
acc
(recur (rest r) (conj acc (first r))))))
Sample output:
user> (reverse-recursively '(1 2 3 4 5 6))
(6 5 4 3 2 1)
user> (reverse-recursively [1 2 3 4 5 6])
(6 5 4 3 2 1)
user> (reverse-recursively {:a 1 :b 2 :c 3})
([:c 3] [:b 2] [:a 1])
Questions:
Is there a more concise way of doing this, i.e. without loop/recur?
Is there a way to do this without using an "accumulator" parameter in the loop?
References:
Whats the best way to recursively reverse a string in Java?
http://groups.google.com/group/clojure/browse_thread/thread/4e7a4bfb0d71a508?pli=1

You don't need to count. Just stop when the remaining sequence is empty.
You shouldn't pre-populate the acc, since the original input may be empty (and it's more code).
Destructuring is cool.
(defn reverse-recursively [coll]
(loop [[r & more :as all] (seq coll)
acc '()]
(if all
(recur more (cons r acc))
acc)))
As for loop/recur and the acc, you need some way of passing around the working reversed list. It's either loop, or add another param to the function (which is really what loop is doing anyway).
Or use a higher-order function:
user=> (reduce conj '() [1 2 3 4])
(4 3 2 1)

For the sake of exhaustivenes, there is one more method using into. Since into internally uses conj it can be used as follows :
(defn reverse-list
"Reverse the element of alist."
[lst]
(into '() lst))

Yes to question 1, this is what I came up with for my answer to the recursion koan (I couldn't tell you whether it was good clojure practice or not).
(defn recursive-reverse [coll]
(if (empty? coll)
[]
(conj (recursive-reverse (rest coll)) (first coll) )))

In current version of Clojure there's a built-in function called rseq. For anyone who passes by.

(defn my-rev [col]
(loop [ col col
result []]
(if (empty? col)
result
(recur (rest col) (cons (first col) result)))))
Q1.
The JVM can not optimize the recursion, a recursive function that would directly and stack overflow. Therefore, in Clojure, which uses the loop/recur. So, without using a function that recur deep recursion can not be defined. (which is also used internally to recur as a function trampoline.)
Q2.
a recursive function by recur, must be tail-recursive. If the normal recursive function change to tail-recursive function, so there is a need to carry about the value of a variable is required as the accumulator.

(defn reverse-seq [sss]
(if (not (empty? sss))
(conj (reverse-seq (rest sss)) (first sss))
)
)

(defn recursive-reverse [coll]
(if (empty? coll)
()
(concat (vector (peek coll)) (recursive-reverse (pop coll )))
)
)
and test:
user=> (recursive-reverse [1])
(1)
user=> (recursive-reverse [1 2 3 4 5])
(5 4 3 2 1)

Related

Adding the elements of a Vector without using `reduce` or `apply`

So I am trying to re-implement the reduce method, so it can add a couple of numbers that normally can be done using reduce, like:
(reduce + [1 2 3]) ;; 6
(newRd + [1 2 3]) ;; 6
So I thought maybe it can be done using a recursive function that adds the first element of the vector every time it is called and do it again for the rest of the vector. Something like this:
(defn newRd [list]
(let [sum 0]
(if (not= 0 (count list))
(+ sum (first list))
(newRd (rest list))
)
)
)
I think I am not doing local storing correctly. Any suggestion or maybe a better approach?
there are two mistakes here in your code:
1) you don't add your current sum to the recursive call result
2) you should return zero when the list is empty
corrected variant:
(defn newRd [list]
(let [sum 0]
(if (not= 0 (count list))
(+ sum (first list)
(newRd (rest list)))
sum)))
in repl:
user> (newRd [1 2 3 4])
10
next, you can update it a bit:
first you don't really need the sum in let statement, since the sum always = 0
second, there is a lib function empty? to check if list is empty.
(defn newRd [list]
(if-not (empty? list)
(+ (first list)
(newRd (rest list)))
0))
but remember: clojure doesnt'do tail call optimization, so it is easy to cause stack owerflow with a long list:
user> (newRd (repeat 1000000 1))
StackOverflowError user/newRd (form-init289434844644272272.clj:73)
so it's preferable to use loop/recur
(defn sum-list [list]
(loop [list list sum 0]
(if (empty? list)
sum
(recur (rest list) (+ sum (first list))))))
in repl:
user> (sum-list (repeat 1000000 1))
1000000
the other option is to make the function itself tail recursive:
(defn newRd [list sum]
(if-not (empty? list)
(recur (rest list) (+ sum (first list)))
sum))
user> (newRd (repeat 1000000 1) 0)
1000000
then you can add the additoinal arity, for not to pass the second parameter in every call:
(defn newRd
([list] (newRd list 0))
([list sum]
(if-not (empty? list)
(recur (rest list) (+ sum (first list)))
sum)))
Further to leetwinksi's answer ...
You might as well implement new-reduce (camel case is not idiomatic) in general:
(defn new-reduce
([f init coll]
(if (seq coll)
(recur f (f init (f init (first coll))) (rest coll))
init))
([f coll]
(if (seq coll)
(reduce f (first coll) (rest coll))
(f))))
Then
(new-reduce + [1 2 3]) ;; 6
This is more or less what the source code for reduce looked like until recently, if you stripped chunking out.
The two-argument version that you use leans on the three-argument version, which you can recur on directly, without an explicit loop. This entails passing f each time, but that's what it used to do. Presumably it's faster to carry an extra argument than to work in a local scope.

Making current function of list recursive Clojure

Hi i am looking for a bit of help with some Clojure code. I have written a function that will take in a list and calculate the qty*price for a list eg. '(pid3 6 9)
What i am looking for is to expand my current function so that it recursively does the qty*price calculation until it reaches the end of the list.
My current function is written like this:
(defn pid-calc [list] (* (nth list 1) (nth list 2)))
I have tried implementing it into a recursive function but have had no luck at all, i want to be able to call something like this:
(pid-calcc '( (pid1 8 5) (pid2 5 6))
return==> 70
Thats as close as i have came to an answer and cannot seem to find one. If anyone can help me find a solution i that would be great. As so far i am yet to find anything that will compile.
​(defn pid-calc [list]
(if(empty? list)
nil
(* (nth list 1) (nth list 2)(+(pid-calc (rest list))))))
You don't need a recursive function. Just use + and map:
(defn pid-calc [list]
(letfn [(mul [[_ a b]] (* a b))]
(apply + (map mul list))))
#sloth's answer, suitably corrected, is a concise and fast enough way to solve your problem. It shows you a lot.
Your attempt at a recursive solution can be (a)mended to
(defn pid-calc [list]
(if (empty? list)
0
(let [x (first list)]
(+ (* (nth x 1) (nth x 2)) (pid-calc (next list))))))
This works on the example, but - being properly recursive - will run out of stack space on a long enough list. The limit is usually about 10K items.
We can get over this without being so concise as #sloth. You might find the following easier to understand:
(defn pid-calc [list]
(let [line-total (fn [item] (* (nth item 1) (nth item 2)))]
(apply + (map line-total list))))
reduce fits your scenario quite well:
(def your-list [[:x 1 2] [:x 1 3]])
(reduce #(+ %1 (* (nth %2 1) (nth %2 2))) 0 your-list)
(reduce #(+ %1 (let [[_ a b] %2] (* a b)) 0 your-list)

How to avoid stackoverflow in clojure recursive function?

Here is an example:
;; Helper function for marking multiples of a number as 0
(def mark (fn [[x & xs] k m]
(if (= k m)
(cons 0 (mark xs 1 m))
(cons x (mark xs (inc k) m))
)))
;; Sieve of Eratosthenes
(defn sieve
[x & xs]
(if (= x 0)
(sieve xs)
(cons x (sieve (mark xs 1 x)))
))
(take 10 (lazy-seq (sieve (iterate inc 2))))
It produces a StackOverflowError.
There are a couple of issues here. First, as pointed out in the other answer, your mark and sieve functions don't have terminating conditions. It looks like they are designed to work with infinite sequences, but if you passed a finite-length sequence they'd keep going off the end.
The deeper problem here is that it looks like you're trying to have a function create a lazy infinite sequence by recursively calling itself. However, cons is not lazy in any way; it is a pure function call, so the recursive calls to mark and sieve are invoked immediately. Wrapping the outer-most call to sieve in lazy-seq only serves to defer the initial call; it does not make the entire sequence lazy. Instead, each call to cons must be wrapped in its own lazy sequence.
For instance:
(defn eager-iterate [f x]
(cons x (eager-iterate f (f x))))
(take 3 (eager-iterate inc 0)) ; => StackOverflowError
(take 3 (lazy-seq (eager-iterate inc 0))) ; => Still a StackOverflowError
Compare this with the actual source code of iterate:
(defn iterate
"Returns a lazy sequence of x, (f x), (f (f x)) etc. f must be free of side-effects"
{:added "1.0"
:static true}
[f x] (cons x (lazy-seq (iterate f (f x)))))
Putting it together, here's an implementation of mark that works correctly for finite sequences and preserves laziness for infinite sequences. Fixing sieve is left as an exercise for the reader.
(defn mark [[x :as xs] k m]
(lazy-seq
(when (seq xs)
(if (= k m)
(cons 0 (mark (next xs) 1 m))
(cons x (mark (next xs) (inc k) m))))))
(mark (range 4 14) 1 3)
; => (4 5 0 7 8 0 10 11 0 13)
(take 10 (mark (iterate inc 4) 1 3))
; => (4 5 0 7 8 0 10 11 0 13)
Need terminating conditions
The problem here is both your mark and sieve functions have no terminating conditions. There must be some set of inputs for which each function does not call itself, but returns an answer. Additionally, every set of (valid) inputs to these functions should eventually resolve to a non-recursive return value.
But even if you get it right...
I'll add that even if you succeed in creating the correct terminating conditions, there is still the possibility of having a stack overflow if the depth of the recursion in too large. This can be mitigated to some extent by increasing the JVM stack size, but this has it's limits.
A way around this for some functions is to use tail call optimization. Some recursive functions are tail recursive, meaning that all recursive calls to the function being defined within it's definition are in the tail call position (are the final function called in the definition body). For example, in your sieve function's (= x 0) case, sieve is the tail call, since the result of sieve doesn't get passed into any other function. However, in the case that (not (= x 0)), the result of calling sieve gets passed to cons, so this is not a tail call. When a function is fully tail recursive, it is possible to behind the scenes transform the function definition into a looping construct which avoids consuming the stack. In clojure this is possible by using recur in the function definition instead of the function name (there is also a loop construct which can sometimes be helpful). Again, because not all recursive functions are tail recursive, this isn't a panacea. But when they are it's good to know that you can do this.
Thanks to #Alex's answer I managed to come up with a working lazy solution:
;; Helper function for marking mutiples of a number as 0
(defn mark [[x :as xs] k m]
(lazy-seq
(when-not (empty? xs)
(if (= k m)
(cons 0 (mark (rest xs) 1 m))
(cons x (mark (rest xs) (inc k) m))))))
;; Sieve of Eratosthenes
(defn sieve
[[x :as xs]]
(lazy-seq
(when-not (empty? xs)
(if (= x 0)
(sieve (rest xs))
(cons x (sieve (mark (rest xs) 1 x)))))))
I was adviced by someone else to use rest instead of next.

If the only non-stack-consuming looping construct in Clojure is "recur", how does this lazy-seq work?

The ClojureDocs page for lazy-seq gives an example of generating a lazy-seq of all positive numbers:
(defn positive-numbers
([] (positive-numbers 1))
([n] (cons n (lazy-seq (positive-numbers (inc n))))))
This lazy-seq can be evaluated for pretty large indexes without throwing a StackOverflowError (unlike the sieve example on the same page):
user=> (nth (positive-numbers) 99999999)
100000000
If only recur can be used to avoid consuming stack frames in a recursive function, how is it possible this lazy-seq example can seemingly call itself without overflowing the stack?
A lazy sequence has the rest of the sequence generating calculation in a thunk. It is not immediately called. As each element (or chunk of elements as the case may be) is requested, a call to the next thunk is made to retrieve the value(s). That thunk may create another thunk to represent the tail of the sequence if it continues. The magic is that (1) these special thunks implement the sequence interface and can transparently be used as such and (2) each thunk is only called once -- its value is cached -- so the realized portion is a sequence of values.
Here it is the general idea without the magic, just good ol' functions:
(defn my-thunk-seq
([] (my-thunk-seq 1))
([n] (list n #(my-thunk-seq (inc n)))))
(defn my-next [s] ((second s)))
(defn my-realize [s n]
(loop [a [], s s, n n]
(if (pos? n)
(recur (conj a (first s)) (my-next s) (dec n))
a)))
user=> (-> (my-thunk-seq) first)
1
user=> (-> (my-thunk-seq) my-next first)
2
user=> (my-realize (my-thunk-seq) 10)
[1 2 3 4 5 6 7 8 9 10]
user=> (count (my-realize (my-thunk-seq) 100000))
100000 ; Level stack consumption
The magic bits happen inside of clojure.lang.LazySeq defined in Java, but we can actually do the magic directly in Clojure (implementation that follows for example purposes), by implementing the interfaces on a type and using an atom to cache.
(deftype MyLazySeq [thunk-mem]
clojure.lang.Seqable
(seq [_]
(if (fn? #thunk-mem)
(swap! thunk-mem (fn [f] (seq (f)))))
#thunk-mem)
;Implementing ISeq is necessary because cons calls seq
;on anyone who does not, which would force realization.
clojure.lang.ISeq
(first [this] (first (seq this)))
(next [this] (next (seq this)))
(more [this] (rest (seq this)))
(cons [this x] (cons x (seq this))))
(defmacro my-lazy-seq [& body]
`(MyLazySeq. (atom (fn [] ~#body))))
Now this already works with take, etc., but as take calls lazy-seq we'll make a my-take that uses my-lazy-seq instead to eliminate any confusion.
(defn my-take
[n coll]
(my-lazy-seq
(when (pos? n)
(when-let [s (seq coll)]
(cons (first s) (my-take (dec n) (rest s)))))))
Now let's make a slow infinite sequence to test the caching behavior.
(defn slow-inc [n] (Thread/sleep 1000) (inc n))
(defn slow-pos-nums
([] (slow-pos-nums 1))
([n] (cons n (my-lazy-seq (slow-pos-nums (slow-inc n))))))
And the REPL test
user=> (def nums (slow-pos-nums))
#'user/nums
user=> (time (doall (my-take 10 nums)))
"Elapsed time: 9000.384616 msecs"
(1 2 3 4 5 6 7 8 9 10)
user=> (time (doall (my-take 10 nums)))
"Elapsed time: 0.043146 msecs"
(1 2 3 4 5 6 7 8 9 10)
Keep in mind that lazy-seq is a macro, and therefore does not evaluate its body when your positive-numbers function is called. In that sense, positive-numbers isn't truly recursive. It returns immediately, and the inner "recursive" call to positive-numbers doesn't happen until the seq is consumed.
user=> (source lazy-seq)
(defmacro lazy-seq
"Takes a body of expressions that returns an ISeq or nil, and yields
a Seqable object that will invoke the body only the first time seq
is called, and will cache the result and return it on all subsequent
seq calls. See also - realized?"
{:added "1.0"}
[& body]
(list 'new 'clojure.lang.LazySeq (list* '^{:once true} fn* [] body)))
I think the trick is that the producer function (positive-numbers) isn't getting called recursively, it doesn't accumulate stack frames as if it was called with basic recursion Little-Schemer style, because LazySeq is invoking it as needed for the individual entries in the sequence. Once a closure gets evaluated for an entry then it can be discarded. So stack frames from previous invocations of the function can get garbage-collected as the code churns through the sequence.

stuck in Clojure recursion

I am trying to write a recursive function in clojure. The function returns the greatest number of given collection. If the collection is emty then it should return nil.
My code is:
(defn gum [coll]
(if (empty? coll)
0
(max (first coll)
(gum (rest coll)))))
Expected result:
(gum [1 2 98 -3]) => 98
(gum [1 9]) => 9
(gum []) => nil
But I am getting:
(gum [1 2 98 -3]) => 98
(gum [1 9]) => 9
(gum []) => 0 (not desired result - should be `nil`)
This is because I have kept the value of (empty? coll) as 0. If I keep it as nil then (gum [1 2 98 -3]) won't work. Any suggestion as how to bring the value of (gum []) as nil and (gum [1 2 98 -3]) as 98 at the same time?
I think you want something like this:
(defn gum [[head & tail]]
(if (empty? tail)
head
(max head (gum tail))))
I'm using destructuring here instead of first and rest, but it's the same as:
(defn gum [coll]
(let [head (first coll)
tail (rest coll)]
(if (empty? tail)
head
(max head (gum tail)))))
But you should try to avoid constructions like (max head (gum tail)), because Clojure can't optimize it. Try using tail recursion with recur whenever possible:
(defn gum [[head & tail]]
(if (empty? tail)
head
(recur (cons (max head (first tail))
(rest tail)))))
recur allows Clojure to use Tail Call Optimization to convert your recursive call into an iterative one, allowing it to be run in a constant stack space. It not only makes your code faster, but also protects it from stack overflow.
You should also consider using Higher Order Functions instead of recursion (as SaltyEgg suggested):
(defn gum [coll]
(if-let [s (seq coll)]
(reduce max s)))
In most cases they provide an easier solution. And they are pretty good optimized.
Try this:
(defn gum [coll]
(if (empty? coll)
nil
(reduce max coll)))
Looks like you are trying to redefine the max function ?
Now if you are looking to understand how the max function works, it ususally a good idea to look at the source (source max) in a repl :
(defn max
"Returns the greatest of the nums."
{:added "1.0"
:inline-arities >1?
:inline (nary-inline 'max)}
([x] x)
([x y] (. clojure.lang.Numbers (max x y)))
([x y & more]
(reduce1 max (max x y) more)))
Note that (apply max []) will throw an exception rather than returning nil : ArityException Wrong number of args (0) passed to: core/max clojure.lang.AFn.throwArity (AFn.java:429)
Edit :
That's why the approach to check first if we want to apply max and then (maybe) apply, as suggested by other answers :
(defn gum [coll]
(if-let [s (seq coll)]
(reduce max s)))
You should not call the same function inside because Clojure does not have tail recursion optimization (TRO). Use (recur arg1 arg2 etc) to iterate on the next step. And don't forget to add an if statement to leave the recursion.
This would work, using same logic as you have described, returning singleton elements instead of zero:
(defn gum [coll]
(if (or (empty? coll)
(singleton? coll))
(first coll)
(max (first coll) (gum (rest coll)))))
with:
(defn singleton? [coll]
(if (first coll) (empty? (rest coll)) false))

Resources