Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clojure loop/recur pattern, is it bad to use?

Tags:

clojure

I'm in the process of learning Clojure, and I'm using 4Clojure as a resource. I can solve many of the "easy" questions on the site, but for me thinking in a functional programming mindset still doesn't come naturally (I'm coming from Java). As a result, I use a loop/recur iterative pattern in most of my seq-building implementations because that's how I'm used to thinking.

However, when I look at the answers from more experienced Clojure users, they do things in a much more functional style. For example, in a problem about implementing the range function, my answer was the following:

(fn [start limit]
  (loop [x start y limit output '()]
    (if (< x y)
      (recur (inc x) y (conj output x))
      (reverse output))))

While this worked, other users did things like this:

(fn [x y] (take (- y x) (iterate inc x)))

My function is more verbose and I had no idea the "iterate" function even existed. But was my answer worse in an efficiency sense? Is loop/recur somehow worse to use than alternatives? I fear this sort of thing is going to happen a lot to me in the future, as there are still many functions like iterate I don't know about.

like image 226
RGrun Avatar asked Sep 18 '15 00:09

RGrun


2 Answers

The second variant returns a lazy sequence, which may indeed be more efficient, especially if the range is big.

The other thing is that the second solution conveys the idea better. To put it differently, it describes the intent instead of implementation. It takes less time to understand it as compared to your code, where you have to read through the loop body and build a model of control flow in your head.

Regarding the discovery of the new functions: yes, you may not know in advance that some function is already defined. It is easier in, say, Haskell, where you can search for a function by its type signature, but with some experience you will learn to recognize the functional programming patterns like this. You will write the code like the second variant, and then look for something working like take and iterate in the standard library.

like image 143
fjarri Avatar answered Sep 22 '22 18:09

fjarri


Bookmark the Clojure Cheetsheet website, and always have a browser tab open to it.

Study all of the functions, and especially read the examples they link to (the http://clojuredocs.org website).

The site http://clojure-doc.org is also very useful (yes, the two names are almost identical but not quite)

like image 31
Alan Thompson Avatar answered Sep 20 '22 18:09

Alan Thompson