The following can be used to inspect applications and values.
(define-syntax ?
(syntax-rules ()
((_ (proc arg0 arg1 ...))
(let* ((args (list arg0 arg1 ...))
(result (apply proc args)))
(format (current-error-port)
";; (~s~{ ~s~}) => ~s\n"
'proc args result)
result))
((_ val)
(let ((result val))
(format (current-error-port)
";; ~s => ~s\n"
'val result)
result))))
The following expression
(let ((x 5))
(? (* (? x) (? x))))
will print three lines.
;; x => 5
;; x => 5
;; (* 5 5) => 25
The following is a more compact alternative to inspect applications.
(define (??-flat-zip l1 l2)
(if (null? l1)
'()
(cons (car l1) (cons (car l2) (??-flat-zip (cdr l1) (cdr l2))))))
(define-syntax ??
(syntax-rules ()
((_ (proc arg0 arg1 ...))
(let* ((args (list arg0 arg1 ...))
(result (apply proc args)))
(format (current-error-port)
";; (~s~{ ~s => ~s~}) => ~s\n"
'proc (??-flat-zip (list 'arg0 'arg1 ...) args) result)
result))))
The following example
(let ((x 5))
(?? (* x x)))
prints just one line.
;; (* x => 5 x => 5) => 25
The macro takes care of side effects
(let ((inc (let ((i 0))
(lambda ()
(let ((j i))
(set! i (+ i 1))
j)))))
(?? (+ (inc) (inc))))
and evaluates inc
just twice.
;; (+ (inc) => 0 (inc) => 1) => 1