Deleteman
Deleteman

Reputation: 8700

What is the difference between these two blocks of Clojure code?

While working on the Clojure Koans, I had to calculate the factorial of a number iterativly, I did find the solution, but I have a question about the difference between 2 solutions, one that works and one that doens't, although I don't understand why:

The one that works:

(defn factorial [n]
   (loop [n n
         acc 1]
     (if (zero? n)
      acc
      (recur (dec n) (* n acc )))
 )

The one that desn't:

(defn factorial [n]
   (loop [n n
         acc 1]
     (if (zero? n)
      1
      (recur (dec n) (* n acc )))
 )

Note that the only difference is the returned value of the If block if the condition is met.

Upvotes: 2

Views: 171

Answers (2)

andrew cooke
andrew cooke

Reputation: 46882

it's hard to work out what you think should be happening for the question to make sense. i think maybe you think loop is doing more than it does? your code is almost equivalent to:

(defn factorial 
  ([n] (factorial n 1)
  ([n acc] 
    (if (zero? n)
      acc
      (recur (dec n) (* n acc)))))

which is a stack-safe version of

(defn factorial 
  ([n] (factorial n 1)
  ([n acc] 
    (if (zero? n)
      acc
      (factorial (dec n) (* n acc)))))

so the acc (or 1) is the final value returned from the function.

all that loop does is give a different target for recur, which is useful if you have some code between the start of the function and the point where you want to repeat. it's basically a label for a goto.

Upvotes: 1

Jon Gauthier
Jon Gauthier

Reputation: 25592

The second factorial function always returns 1. The code is built to use an accumulator variable (acc), and the first code block gets it right by returning this accumulator variable.

A factorial function can be written to return 1, though, if an accumulator variable is not used. Since this method does not utilize loop / recur, it can cause a stack overflow easily: try (fact 5000).

(defn factorial [x]
  (if (<= x 1)
      1
      (* x (factorial (- x 1)))))

(source)

Upvotes: 5

Related Questions