[pro] couple questions about dynamic bindings
Tobias C Rittweiler
tcr at freebits.de
Thu Dec 30 12:32:55 UTC 2010
In article <4CBC918B-9B18-4C07-B289-A95040C33919 at gerg.org>,
Greg Gilley <ggilley at gerg.org> wrote:
> There are some tests in the common-lisp test suite with dynamic binding that
> I don't understand. If someone could help shed some light on them I'd
> appreciate it.
>
> progv makes it's arguments special. I don't understand how they can be a
> different special than the one declared in the let. I'd love an explanation.
>
> (let ((x 0))
> (declare (special x))
> (progv '(x) ()
> (boundp 'x))) ==> NIL
>
> (let ((x 0))
> (declare (special x))
> (progv '(x) () (setq x 1))
> x) ==> 0
>
> Thanks,
>
> Greg
Notice that PROGV does *not* make a binding special. If you
want to do that at run-time, you have to use
(proclaim `(special ,name))
For illustration, consider the following case:
CL-USER> (progv '(.x.) '(:progv)
(let ((.x. :inner-let)) #'(lambda () .x.)))
#<FUNCTION (LAMBDA ()) {CDA3DCD}>
CL-USER> (let ((.x. :outer-let)) (funcall *))
:INNER-LET
PROGV can /basically/ be thought of as being a macro
that expands to
(let ((old-values (mapcar #'symbol-value <VARS>)))
(unwind-protect
(progn (mapc #'(setf symbol-value) <VALS> <VARS>)
. <BODY>)
(mapc #'(setf symbol-value) old-values <VARS>)))
It's more complicated than that but I think it suffices as
a mental model.
In case of multi-threading, its implementation is even more
complicated because it "must" be ensured that PROGV establishes
thread-local bindings. (The quotes around "must" because
multi-threading is, as you probably know, not part of the ANSI
standard.)
Consider:
CL-USER> (defparameter *foo* :global)
*FOO*
CL-USER> (sb-thread:make-thread #'(lambda ()
(progv '(*foo*) '()
(setq *foo* :thread))))
#<SB-THREAD:THREAD RUNNING {CEEBFA9}>
CL-USER> (sb-thread:join-thread *)
:THREAD
CL-USER> *foo*
:GLOBAL
Regards,
-T.
More information about the pro
mailing list