(define (compose3 f g)
  (lambda (x y z)
    (call-with-values (lambda () (g x y z)) f)))

(define (iterate3 f n)
  (if (= n 0)
      (lambda (x y z) (values x y z))
      (compose3 f (iterate3 f (- n 1)))))

(define e
  (call-with-values
    (lambda ()
      (apply
       (iterate3
	(lambda (x acc1 acc2)
	  (values (+ x 1) (* x acc1) (+ (/ 1.0 acc1) acc2)))
	10)
       '(1 1 0)))
    (lambda (x y z) z)))

(define (split ls)
  (if (or (null? ls) (null? (cdr ls)))
      (values ls ())
      (call-with-values
        (lambda () (split (cddr ls)))
	(lambda (odds evens)
	  (values (cons (car ls) odds)
		  (cons (cadr ls) evens))))))

(define (stream-cddr str)
  (stream-cdr (stream-cdr str)))

(define (stream-cadr str)
  (stream-car (stream-cdr str)))

(define (1st delayed-vals) 
  (call-with-values 
    (lambda () (force delayed-vals))
    (lambda (x y) x)))

(define (2nd delayed-vals)
  (call-with-values
    (lambda () (force delayed-vals))
    (lambda (x y) y)))

(define (split-stream str)
  (if (or (null? str) (null? (stream-cdr str)))
      (values str ())
      (let ((delayed-vals (delay (split-stream (stream-cddr str)))))
	(values (stream-cons (stream-car str) 
			     (1st delayed-vals))
		(stream-cons (stream-cadr str) 
			     (2nd delayed-vals))))))