; Using continuation passing style to implement factorial ; non-tail recursive factorial function ; NOT tail recursive because the recursive ; call to fact is in an operand position (define rfact (lambda (n) (if (zero? n) 1 (* n (rfact (- n 1)))))) ; tail recursive factorial function ; tail call because fact is in tail position (define (tail-fact n m) (if (zero? n) m (tail-fact (- n 1) (* m n)))) (define (tfact n) (tail-fact n 1)) ; A better way to write tfact is to use ; a named let so that the gobal namespace ; is not populated with extra names (define fact (lambda (n) (let tfact ((n n) (m 1)) (if (zero? n) m (tfact (- n 1) (* m n)))))) ; The tail call version is just fine, since Scheme turns it ; into an iteration. But let's look at the CPS version just ; to see how it is done, before looking at a more complex one (define cps-fact (lambda (n k) ;; the parameter k is the "continuation" procedure (if (zero? n) (k 1) (cps-fact (- n 1) ;; cps-fact in tail position (lambda (m) (k (* n m))))))) ;; pass (* n m) as new k ; pass in the identity function as parameter k (define (cfact n) (cps-fact n (lambda (x) x))) ; What happens in the cps-fact case is that we build up a list of ; nested lambda functions that end up expanding out like this ; for n = 1 ((lambda (m) ((lambda (x) x) (* 1 m))) 1) ; for n = 2 ((lambda (m) ((lambda (m) ((lambda (x) x) (* 2 m))) (* 1 m))) 1) ; for n = 3 ((lambda (m) ((lambda (m) ((lambda (m) ((lambda (x) x) (* 3 m))) (* 2 m))) (* 1 m))) 1) ; and so on for n = 4, 5, ...