On 1/17/07 10:07 PM, "Matt Pillsbury" <pillsbury@...> wrote:
> Hi, all,
> When I try:
> * (progv '(*x*) '(1) *x*)
> ; caught WARNING:
> ; undefined variable: *X*
> ; caught WARNING:
> ; This variable is undefined:
> ; *X*
> ; compilation unit finished
> ; caught 2 WARNING conditions
> as well as returning 1, as it should. This warning doesn't really
> make much sense to me---why should it be a problem if *x* is
> undefined if the whole point of PROGV is to establish bindings? FWIW,
> neither CLISP nor the trial versions of ACL and LispWorks complain
> about this. Is there a straightforward way to eliminate these warnings?
The warning is because *X* has not been declared globally special at the
point at which it appears as a variable reference in your code. It doesn't
matter that it will be BOUNDP at runtime. The following example may make
that a little clearer:
(defun wrap-progv (thunk) (progv '(*x*) '(1) (funcall thunk)))
(wrap-progv (lambda () *x*))
When the compiler sees the reference to *x* in the call to WRAP-PROGV on the
second line, it has no knowledge that it will be bound at runtime.
SBCL's behavior is suggested due to section 184.108.40.206.1, and in particular
220.127.116.11.1.2, of the ANSI specification.
`` There are three kinds of variables: lexical variables, dynamic variables,
and constant variables.''
`` A variable is a dynamic variable if one of the following conditions hold:
* It is locally declared or globally proclaimed special.
* It occurs textually within a form that creates a dynamic binding for a
variable of the same name, and the binding is not shadowed by a form that
creates a lexical binding of the same variable name.''
*X* has not been declared special globally or locally. The second statement
is somewhat confusing in the context of PROGV, since in your example it
could be inferred that *X* is indeed bound during the execution of the body.
However, the WRAP-PROGV example above shows that PROGV does not operate
textually in general.
If *X* is not a dynamic variable, and it has not been bound lexically or
declared to be a constant, then it does not fall into any of the categories
in the first quoted statement and thus the program invokes unspecified
behavior. SBCL here issues a warning to indicate this as part of a general
policy of warning when unspecified behavior is invoked by the program.
The fix is really quite trivial: simply (DECLAIM (SPECIAL *X*)) before
executing forms that refer to the dynamic value of *X*.
The fact that ACL, LispWorks, and CLISP do not warn is also compounded by
the fact that all three of these implementations use an interpreter by
default at the REPL, where SBCL uses the compiler. Indeed, if you enable the
SBCL interpreter by (setf sb-ext:*evaluator-mode* :interpret), SBCL does not
warn. However, that isn't actually the fix to your problem :-)