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
On Sun, 26 Dec 2010 16:04:06 -0800, Greg Gilley said:
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.
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
On Sun, Dec 26, 2010 at 4:04 PM, Greg Gilley ggilley@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
pro mailing list pro@common-lisp.net http://common-lisp.net/cgi-bin/mailman/listinfo/pro
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
On Dec 27, 2010, at 8:43 AM, Peter Seibel wrote:
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
On Sun, Dec 26, 2010 at 4:04 PM, Greg Gilley ggilley@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
pro mailing list pro@common-lisp.net http://common-lisp.net/cgi-bin/mailman/listinfo/pro
-- Peter Seibel http://www.codequarterly.com/
In article 4CBC918B-9B18-4C07-B289-A95040C33919@gerg.org, Greg Gilley ggilley@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.