Comment 4 for bug 596519

Revision history for this message
Douglas Katzman (dougk) wrote :

I suspect the bug reporter is confusing the issues of printing as _actually_ readable (preserving semantics of the closure with respect to what it captured), and printing in some way that reveals information about the closed-over values from a debugging perspective. Or at least I don't understand the intent.

It is most certainly not the case that Clisp can "readably" print any closure if you expect that to give back (from a subsequent READ) either the EQ object, or an object that at least shares the same closure variables. In case there is doubt about what I mean, let's be clear:

./clisp
(defun f (x) (list (lambda (y) (setq x y)) (lambda () x)))
(setq *funs* (f 1))
(setq *first* (read-from-string (let ((*print-closure* t)) (write-to-string (car *funs*)))))
(funcall *first* 42)
(print (funcall (second *funs*)))

So despite that I "readably" printed a closure, READ didn't do what I want. The above prints 1, not 42, because *FIRST* isn't actually the correct object after print and read.

In terms of how one can examine a closure, that's fairly simple, more or less what Nikodemus said:

(defun f (x y) (lambda (z) (+ (incf x) y z)))
* (function-lambda-expression (f 1 2)) =>
(LAMBDA (Z) (+ (INCF X) Y Z))
and if you want to see the closed-over values:
* (sb-vm:hexdump (f 1 2))
10018C0C70: 5030008300000335
10018C0C78: 0000000052B1DA80 = 693693760
10018C0C80: 0000000000000004 = 2
10018C0C88: 00000010018C0C6F = #<value cell 1 {10018C0C6F}>

In terms of constructing an arbitrary closure, I don't see that as a useful feature. To construct a closure you should call the function that constructs a closure. Moreover I don't know what it means to read back in a compiled function.