Here's an iterative implementation:
(defun fact (n)
(check-type n unsigned-byte)
(loop for i from 0 to n
for fact = 1 then (* fact i)
finally (return fact)))
CPS:
(defun fact (x)
(labels ((fact-aux (n k)
(cond ((zerop n)
(funcall k 1))
(t
(fact-aux (1- n) (lambda (m)
(funcall k (* m n))))))))
(check-type x (integer 0 *))
(fact-aux x #'identity)))
There's less wrong with the above than there used to be. It is now the case that these functions simply behave in odd ways when given negative or non-integers; and of course the recursive (first) definition can still overflow the stack.
I still prefer my take, of course...:
(defun fact (n)
;; in a _(declarations-are-assertions) compiler like _(CMUCL) or _(SBCL),
;; I might write (_H(DECLARE) (TYPE UNSIGNED-BYTE N)) here.
(_H(check-type) n _H(unsigned-byte))
(let ((result 1))
(declare (type unsigned-byte result))
(do ((i n (1- i)))
((= i 0) result)
(setf result (* result i)))))
-- ChristopheAre the HyperSpec references intentional here? -- Roland Kaufmann
Well, I put them in because people might be interested in the difference between CHECK-TYPE and DECLARE, and might want to look them up. -- (Christophe)
;; A tail-recursive version, w/o an auxiliary function, inspired by Winston's fibonacci function in Lisp, 3rd edition
(defun fact (n &optional (so-far 1))
(if (<= n 1)
so-far
(fact (- n 1) (* n so-far))))
--Above function overflows stack on Lispworks. --I also use Lispworks (LWM 4.4.5). I don't have any issues with this function, once compiled, for values up to 10000. It seems to hog the machine for (fact 100000), no doubt understandably. Olivier --If the result is not diaplayed, (fact 10000) takes 0.5 sec. and (fact 100000) takes 69 sec. on 1.8 MHz G5
;; Factorial using anonymous recursive function
(funcall ((lambda (f) #'(lambda (n) (funcall f f n)))
#'(lambda (f n)
(if (= n 0)
1
(* n (funcall f f (- n 1))))))
x)
Here's another iterative implementation: