(define revappend
  (lambda (x y)
    (if (null? x) y
	(revappend (cdr x) (cons (car x) y)))))

(define reverse
  (lambda (x)
    (revappend x '())))

(define map
  (lambda (f x)
    (if (null? x) '() (cons (f (car x)) (map f (cdr x))))))

(define print-digit (lambda (x) (write-char x)))

(define digits
  (lambda (x cs)
    (if (= x 0) cs
	(let ((y (/ x 10))
	      (d (- x (* y 10)))
	      (c (integer->char (+ d (char->integer (string-ref "0" 0))))))
	  (digits y (cons c cs))))))

(define print-int
  (lambda (x)
    (cond ((= x 0) (write "0"))
	  ((< x 0) (begin (write "-") (print-int (- 0 x))))
	  (else (map print-digit (digits x '()))))))

(define print-pair
  (lambda (x)
    (begin 
      (write "(")
      (print-value (car x))
      (write " . ")
      (print-value (cdr x))
      (write ")"))))

(define print-string
  (lambda (x)
    (begin
      (write "\"")
      (write x)
      (write "\""))))

(define print-char
  (lambda (x)
    (begin
      (write "'")
      (write-char x)
      (write "'"))))

(define print-value
  (lambda (x)
    (cond ((null? x) (write "'()"))
	  ((integer? x) (print-int x))
	  ((pair? x) (print-pair x))
	  ((char? x) (print-char x))
	  ((string? x) (print-string x))
	  ((input-port? x) (write "#indesc"))
	  ((output-port? x) (write "#outdesc"))
	  ((procedure? x) (write "#fn"))
	  (else (write "#t")))))

(define print-newline (lambda () (write-char (integer->char 10))))
    
(define print-val (lambda (x) (print-value x) (print-newline)))

(define z
  (begin
    (print-val '())
    (print-val #t)
    (print-val 123)
    (print-val (list 3 4 5))
    (print-val (integer->char 65))
    (print-val "foo")
;    (print-val std-in)
;    (print-val std-out)
    (print-val print-val)))
