Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When to use pure recursion and when to use loop/recur?

"pure recursion" is a made-up term here, please forgive.

Here are two examples using two different recursion approaches. What are the guidelines of usage of one over another?

(defn take-while
  "Returns a lazy sequence of successive items from coll while
  (pred item) returns true. pred must be free of side-effects."
  {:added "1.0"
   :static true}
  [pred coll]
  (lazy-seq
   (when-let [s (seq coll)]
       (when (pred (first s))
         (cons (first s) (take-while pred (rest s)))))))

(defn take-last
  "Returns a seq of the last n items in coll.  Depending on the type
  of coll may be no better than linear time.  For vectors, see also subvec."
  {:added "1.1"
   :static true}
  [n coll]
  (loop [s (seq coll), lead (seq (drop n coll))]
    (if lead
      (recur (next s) (next lead))
      s)))
like image 411
Yuriy Zubarev Avatar asked Jan 11 '13 05:01

Yuriy Zubarev


People also ask

Should I use recursion or loops?

Recursion is a better way of solving a problem as compared to looping . In most cases time complexity of a recursive solution is better than the loop one . Most of the software company in their interviews prefer a recursive solution.

Which is better while loop or recursion?

No, recursion isn't faster than loops, because loops have built-in support in CPUs, whereas recursion is implemented using the generally slower function call / return mechanism. That said, recursion can be made to be as fast as loops by a good compiler, when the code is properly written.

Are loops faster than recursion?

In general, no, recursion will not be faster than a loop in any realistic usage that has viable implementations in both forms. I mean, sure, you could code up loops that take forever, but there would be better ways to implement the same loop that could outperform any implementation of the same problem via recursion.

Can we use while loop in recursion?

Is a while loop intrinsically a recursion? then, yes, a while loop is a form of recursion. Recursive functions are another form of recursion (another example of recursive definition).


Video Answer


3 Answers

A few factors to consider:

  • loop/recur doesn't consume stack space - so it's the right choice if you are going to do deeply nested recursion that might otherwise cause a StackOverflowError
  • loop/recur is faster - it's one of the most efficient constructs in Clojure, done correctly it should match the speed of an equivalent for loop in Java code
  • normal recursion is more idiomatic - on average it tends to give you clearer, more functional code whereas loop/recur tends to push you more towards an imperative, iterative style
  • loop/recur has more restrictions - you can only recur in tail position, you can't do mutual recursion between two different functions, etc. Sometimes it simply isn't possible to make loop/recur work, at other times you may need to contort your code to do so.
like image 103
mikera Avatar answered Oct 30 '22 05:10

mikera


The only one reason to use lazy-seq/lazy-cons mechanism is generating lazy sequences. If you don't need them then loop/recur should undoubtedly be used.

like image 42
mobyte Avatar answered Oct 30 '22 05:10

mobyte


Use plain recursion when you are writing your function in the first place. Then change this to recur once you have it all working, if you can.

One problem with TCO is that if you balk your recursion up, you get an infinite look. Without, your code crashes nicely with a stack overflow, which is what you want. I didn't like the idea of recur when I first heard about it --most optimisations should just happen -- but being able to switch it off is nice.

like image 24
Phil Lord Avatar answered Oct 30 '22 04:10

Phil Lord