[gambit-list] closure introspection

Christian christian at pflanze.mine.nu
Tue Aug 1 15:09:00 EDT 2006


Hello

I want to be able to see the values which are visible by some closure
(without having to enter the closure with the stepper and look at the
,e output, and I'd like to be able to do that also for compiled code
(if compiled with the 'debug option)).

Since in Scheme (or functional languages in general), closures are a
common alternative to structures for storing data, they should be as
easily inspectable (for debugging purposes at least) as the latter.

Sometimes I'm using ##vector-ref for checking the contents of a
closure data structure, but that's rather tedious, since the
relationship between the variable name and the index in the structure
isn't straight-forward. (See below for an example where I'm trying to
get at the relevant information through manual inspection.)

I'm imagining something like:

> (procedure-prettyprint/environment someclosure)
#<procedure #2 someclosure
            len: 5
            data: #(0 0 0 0 0)
            pos: 0>

where len, data and pos are the bindings which are being stored along
with the closure and maybe also those stored with their "parents" (if
chaining of environments is being used; it seems that the gambit
compiler is using boxing and stores away a copy of the reference to
the box directly with the closure instead of chaining).

Would it be possible to display the above data from the currently
available data structures? Do you imagine I could implement it myself?

Thanks
Christian.



(define showval (gensym))

(define (alternator len)
  (let* ((data (make-vector len))
	 (pos 0)
	 (incpos! (lambda ()
		    (set! pos (let ((p (+ pos 1)))
				(if (>= p len)
				    0
				    p))))))
    (lambda (#!optional v)
      (cond ((eq? v showval)
	     (vector len data pos))
	    (v
	     (incpos!)
	     (vector-set! data pos v))
	    (else
	     (incpos!)
	     (vector-ref data pos))))))


When run in the interpreter:

> (define a (alternator 5))
> (##vector-length a)
4
> (##vector-ref a 0)
#<procedure #2>
> (pp #2)
#<procedure #2>  -> must be compiled, thus (in this case) be some gambit internal
> (##vector-ref a 1)
#(#(#(#(#(#(#(#f
              #<procedure #3 ##cprc-seq>
              #(#(#(#(#....endless
> (##vector-ref a 2)
#<procedure #4 a>
> (pp #4)
(lambda (#!optional v)
  (cond ((eq? v showval) (vector len data pos))
        (v (incpos!) (vector-set! data pos v))
        (else (incpos!) (vector-ref data pos))))
> (##vector-ref a 3)
#(#(#(#(#f #<procedure #5 alternator> 5) #(0 0 0 0 0)) 0) #<procedure #6>)
> (pp #5)
(lambda (len)
  (let ((data (make-vector len)))
    (let ((pos 0))
      (let ((incpos! (lambda ()
                       (set! pos (let ((p (+ pos 1))) (if (>= p len) 0 p))))))
        (lambda (#!optional v)
          (cond ((eq? v showval) (vector len data pos))
                (v (incpos!) (vector-set! data pos v))
                (else (incpos!) (vector-ref data pos))))))))
> (pp #6)
(lambda () (set! pos (let ((p (+ pos 1))) (if (>= p len) 0 p))))
>


When compiled with 'debug:

> (bruse exp-closuredisplay)
> (define a (alternator 5))
> (##vector-length a)
4
> (##vector-ref a 0)
#<procedure #2>
> (pp #2)
(lambda (#!optional v)
  (cond ((eq? v showval) (vector len data pos))
        (v (incpos!) (vector-set! data pos v))
        (else (incpos!) (vector-ref data pos))))
> (##vector-ref a 1)
#(0 0 0 0 0)
> (##vector-ref a 2)
5
> (##vector-ref a 3)
#&0





More information about the Gambit-list mailing list