Skip to content

Instantly share code, notes, and snippets.

@ceving
Created July 14, 2023 11:55
Show Gist options
  • Save ceving/098d14c4fb7c2da6bd9172e7c5849ac0 to your computer and use it in GitHub Desktop.
Save ceving/098d14c4fb7c2da6bd9172e7c5849ac0 to your computer and use it in GitHub Desktop.
Debug expressions in Scheme

Debug expressions in Scheme

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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment