HiveBrain v1.2.0
Get Started
← Back to all entries
patternMinor

Basic reverse function

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
functionreversebasic

Problem

I am just starting out in my Clojure journey and I wonder if anybody can point out my beginners mistakes in my function below that simply reverses a list. I know that there is already a reverse function so this is purely for learning.

(defn rev
  ([l]
   (if (= (count l) 1) l (rev '() l)))
  ([l orig]
   (if (= (count orig) 0)
     l
     (rev (conj l (first orig)) (rest orig)))))


In my defence, it does work, but what I am finding myself doing a lot in Clojure is overloading the arguments list to take into account when I need a working list like in this example where I conj new items onto.

Solution

Sometimes using arity overloading like you've done is the best way to write a function.

I tried to rewrite your function using destructuring, like this:

(defn rev [[x & more]]
  (if more
    ...


however, it doesn't really work because you need some way of storing your "result sequence" in progress, which in your function is l. Because we're trying to write a reverse function, it's hard to do what we want without having some way of "building up" the sequence as we go and storing it in an intermediate value.

Taking a look at how reverse is actually implemented in Clojure, we can see that a more concise way to express this idea of iterating over a sequence and building up a result sequence is by using reduce with a starting value of '():

(defn reverse [coll]
  (reduce conj '() coll))


The magic behind this is that we're starting with a seq, '(). When you conj something onto a seq, it adds it to the beginning, not the end. So what this does is it starts with an empty seq, then goes through the input list items one by one and adds them to the beginning of the result list, so that you end up with a list that's reversed.

EDIT: Leonid has a more thorough answer here.

Code Snippets

(defn rev [[x & more]]
  (if more
    ...
(defn reverse [coll]
  (reduce conj '() coll))

Context

StackExchange Code Review Q#45748, answer score: 3

Revisions (0)

No revisions yet.