Discussion:
couple questions about dynamic bindings
Greg Gilley
2010-12-27 00:04:06 UTC
Permalink
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
Martin Simmons
2010-12-27 16:32:10 UTC
Permalink
Post by Greg Gilley
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
The type of binding is the same, but the real power of progv is that it
evaluates the list of variables, unlike let where the variable names are fixed
when the code is created. See also the difference between set and setq.
--
Martin Simmons
LispWorks Ltd
http://www.lispworks.com/
Peter Seibel
2010-12-27 16:43:21 UTC
Permalink
I'm assuming you're surprised by the results of the forms you give
below. The issue isn't that progv makes "a differest special"--it
makes a new binding. So in the first form you've created a new binding
for x with no supplied value so boundp returning NIL seems about
right. And in the second case, you create a binding, assign it a
value, and then leave the scope of the binding. Or I'm missing
something about your question.

-Peter
Post by Greg Gilley
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
_______________________________________________
pro mailing list
http://common-lisp.net/cgi-bin/mailman/listinfo/pro
--
Peter Seibel
http://www.codequarterly.com/
Greg Gilley
2010-12-27 18:03:25 UTC
Permalink
Nope, that was it. I had thought progv would treat the binding with no argument like a free binding. Instead, it explicitly unbinds the variable.

Thanks!

Greg
Post by Peter Seibel
I'm assuming you're surprised by the results of the forms you give
below. The issue isn't that progv makes "a differest special"--it
makes a new binding. So in the first form you've created a new binding
for x with no supplied value so boundp returning NIL seems about
right. And in the second case, you create a binding, assign it a
value, and then leave the scope of the binding. Or I'm missing
something about your question.
-Peter
Post by Greg Gilley
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
_______________________________________________
pro mailing list
http://common-lisp.net/cgi-bin/mailman/listinfo/pro
--
Peter Seibel
http://www.codequarterly.com/
Tobias C Rittweiler
2010-12-30 12:32:55 UTC
Permalink
Post by Greg Gilley
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.

Loading...