; continuation passing style

(define (but-last xs)
  (reverse (cdr (reverse xs))))

(define (last xs) (car (reverse xs)))

(define (cps f)
  (lambda args
    (let ((f-args (but-last args)) (k (last args)))
      (k (apply f f-args)))))

(define (factorial n)
  (if (= n 0)
      1
      (* n (factorial (- n 1)))))

(display (factorial 5)) (newline)

(define (factorial& n k)
  ((cps =) n 0 (lambda (b)
                 (if b 
                     (k 1)
                     ((cps -) n 1 (lambda (n-1)
                                    (factorial& n-1 (lambda (f)
                                                      ((cps *) n f k)))))))))

(display (factorial& 5 (lambda (x) x))) (newline)

(define (fact n a)
  (if (= n 0)
      a
      (fact (- n 1) (* n a))))

(define (factorial n)
  (fact n 1))

(display (factorial 5)) (newline)

(define (fact& n a k)
  ((cps =) n 0 (lambda (b)
                 (if b
                     (k a)
                     ((cps -) n 1 (lambda (n-1) 
                                    ((cps *) n a (lambda (n*a)
                                                   (fact& n-1 n*a k)))))))))

(define (factorial& n k)
  (fact& n 1 k))
 
(display (factorial& 5 (lambda (x) x))) (newline)

(define (pyth x y)
  (sqrt (+ (* x x) (* y y))))

(display (pyth 3 4)) (newline)

(define (pyth& x y k)
  ((cps *) x x (lambda (x2)
                 ((cps *) y y (lambda (y2)
                                ((cps +) x2 y2 (lambda (x2+y2)
                                                 ((cps sqrt) x2+y2 k))))))))

(display (pyth& 3 4 (lambda (x) x))) (newline)