Subject: Re: Environments in DrScheme
From: rpw3@rigden.engr.sgi.com (Rob Warnock)
Date: 2000/07/12
Newsgroups: comp.lang.scheme
Message-ID: <8kglql$4aiqf$1@fido.engr.sgi.com>
Kenneth Kellum  <kellum@mathcs.sjsu.edu> wrote:
+---------------
| It may well be that DrScheme is not suited for what I was trying to do.
| I'm teaching a course out of Abelson and Sussman's SICP.  In explaining
| local state variables, following the text, it would be nice if I could show
| my students the environment saved when a lambda is evaluated.
+---------------

In *any* Scheme that compiles the code an/or deletes inaccessible
or unused variables and/or stack-allocates non-closed-over lexicals,
the notion of an "environment" is much more subtle than the textbook
description of a simple interpreter. That is, the environment saved
with a closure (the result of a lambda evaluation) is not required to
contain any variable that isn't referenced by that closure, so in many
common cases the saved environment will be minimal or even empty.

However, you could hack up some "printf-style" debugging hooks that may
do enough of what you are looking for to be useful. For example [note:
uses MzScheme's non-hygenic "define-macro", similar to CL's "defmacro"]:

	(define debug-log-size 1000)
	(define debug-log-index 0)
	(define debug-log #f) ; set later
	(define (clear-debug-log)
	  (set! debug-log-index 0)
	  (set! debug-log (make-vector debug-log-size #f)))
	(clear-debug-log)

	(define (debug-logger tag item)
	  (vector-set! debug-log debug-log-index (list tag item))
	  (set! debug-log-index (modulo (+ debug-log-index 1) debug-log-size)))

	(define-macro log-closure
	  (lambda (name . vars-of-interest)
	    `(debug-logger (string-append "closure: " (symbol->string ',name))
	       (list ,@(map (lambda (x) (list 'cons (list 'quote x) x))
			    vars-of-interest)))))

Then you can do stuff like this:

	> (clear-debug-log)
	> (define (make-adder amount)
	    (log-closure make-adder amount) ;DEBUG
	    (lambda (x)
	      (+ x amount)))
	> (define add5 (make-adder 5))
	> (define add17 (make-adder 17))
	> (pretty-print debug-log)
	#1000(("closure: make-adder" ((amount . 5)))
	      ("closure: make-adder" ((amount . 17)))
	      #f)
	> 

Or if what you really wanted was to print out a message when the closure
was *executed*, that's actually somewhat easier:

	(define-macro debug-print
	  (lambda (tag . vars-of-interest)
	    `(begin
	       (display "DEBUG: " (current-error-port))
	       (display ,tag (current-error-port))
	       (display ":" (current-error-port))
	       (for-each (lambda (name value)
			   (display " " (current-error-port))
			   (display name (current-error-port))
			   (display "=" (current-error-port))
			   (display value (current-error-port)))
			 ',vars-of-interest
			 (list ,@vars-of-interest))
	       (newline (current-error-port)))))

Then:

	> (define (make-adder amount)
	    (lambda (x)
	      (debug-print "make-adder closure" amount x) ;DEBUG
	      (+ x amount)))
	> (define add5 (make-adder 5))
	> (define add17 (make-adder 17))
	> (add5 23)
	DEBUG: make-adder closure: amount=5 x=23
	28
	> (add17 23)
	DEBUG: make-adder closure: amount=17 x=23
	40
	> 


-Rob

-----
Rob Warnock, 41L-955		rpw3@sgi.com
Applied Networking		http://reality.sgi.com/rpw3/
Silicon Graphics, Inc.		Phone: 650-933-1673
1600 Amphitheatre Pkwy.		PP-ASEL-IA
Mountain View, CA  94043