Reputation: 523
I don't know why the code below is wrong:
(defn factorial [n]
(loop [n n
acc 1]
(if (zero? n)
acc
(recur (* acc n)(dec n)))))
(= 1 (factorial 1))
How does recur
work?
Upvotes: 1
Views: 148
Reputation: 13473
The arguments to the recur
are the wrong way round.
n
should become (dec n)
acc
should become (* acc n)
So it should be
(recur (dec n) (* acc n))
We can recast the given algorithm to see what's going on inside it.
If we represent the pair of arguments as a vector, the function that generates the next pair is
(fn [[n acc]] [(* acc n) (dec n)])
We can generate the endless sequence of possible pairs for a given no
by applying iterate
to the function above, starting with [no 1]
.
(fn [no]
(iterate (fn [[n acc]] [(* acc n) (dec n)]) [no 1]))
Applying this to 1
generates
([1 1] [1 0] [0 0] [0 -1] ...)
We stop at element 2, the first with an initial 0
, returning the other 0
.
If we put the arguments the right way round, we can get the proper factorial
thus:
(defn factorial [no]
((comp second first)
(drop-while
(comp not zero? first)
(iterate (fn [[n acc]] [(dec n) (* acc n)]) [no 1]))))
This returns the second
element of the first
pair in the sequence with a zero first
(Duh!).
Hopelessly overcomplicated for normal use, but does it work?
=> (map factorial (range 6))
(1 1 2 6 24 120)
Yes.
Upvotes: 3