Ad

A fun implementation using infinite lists. Since everything is evaluated lazily this isn't all that less (if any less) efficient.

Just define an infinite stream of factorials and the pick out the one you want.

Code
Diff
  • #lang racket
    
    (provide factorial)
    
    (define stream-combine
      (lambda (op)
        (lambda (s1 s2)
            (let ((h1 (stream-first s1))
                  (h2 (stream-first s2)))
              (stream-cons (op h1 h2) 
                     ((stream-combine op) (stream-rest s1) (stream-rest s2)))))))
    
    (define ones (stream-cons 1 ones))
    (define nats (stream-cons 1 ((stream-combine +) ones nats)))
    (define facts (stream-cons 1 ((stream-combine *) facts nats)))
    
    (define (factorial n)
      (if (< n 0) 1 
        (stream-ref facts n)))
    • #lang racket
    • (provide factorial)
    • (define stream-combine
    • (lambda (op)
    • (lambda (s1 s2)
    • (let ((h1 (stream-first s1))
    • (h2 (stream-first s2)))
    • (stream-cons (op h1 h2)
    • ((stream-combine op) (stream-rest s1) (stream-rest s2)))))))
    • (define ones (stream-cons 1 ones))
    • (define nats (stream-cons 1 ((stream-combine +) ones nats)))
    • (define facts (stream-cons 1 ((stream-combine *) facts nats)))
    • (define (factorial n)
    • (define (rec-factorial n result)
    • (if (<= n 0) result (rec-factorial (sub1 n) (* result n))))
    • (rec-factorial n 1))
    • (if (< n 0) 1
    • (stream-ref facts n)))

A cleaner version in my opinion

Code
Diff
  • #lang racket
    
    (provide factorial)
    
    (define factorial
       (lambda (n)
         (cond
          ((<= n 1) 1)
          (#t (* n (factorial (- n 1)))))))
    • #lang racket
    • (provide factorial)
    • (define (factorial n)
    • (define (rec-factorial n result)
    • (if (<= n 0) result (rec-factorial (sub1 n) (* result n))))
    • (rec-factorial n 1))
    • (define factorial
    • (lambda (n)
    • (cond
    • ((<= n 1) 1)
    • (#t (* n (factorial (- n 1)))))))