burke@pollux.usc.edu (Sean Burke) (08/13/89)
Here's the code which was the culprit, condensed to essentials, from walk.lisp: ;;; ;;; VARIABLE-GLOBALLY-SPECIAL-P is used to ask if a variable has been ;;; declared globally special. Any particular CommonLisp implementation ;;; should customize this function accordingly and send their customization ;;; back. ;;; (defun variable-globally-special-p (symbol) (or (not (null (member symbol *globally-special-variables* :test #'eq))) (when (eval `(flet ((ref () ,symbol)) (let ((,symbol '#,(list nil))) (and (boundp ',symbol) (eq ,symbol (ref)))))) (push symbol *globally-special-variables*) t))) The above code would choke if symbol were a constant, such as nil, t or a keyword, since the let form attempts to bind symbol. I am trying to figure out what this code is trying to do. The flet defines ref so that it will return the global binding of symbol, then the let binds symbol to (list nil), presumably a fresh cons which could not be the value of any previous binding. Within the let then, symbol is bound and could never be eq the global binding of symbol, even if symbol had been declared special. So this code must be trying to determine whether symbol were PROCLAIMed special, in which case even the let form binds the special variable, and thus ref would return the new binding created by let. Is this the implied meaning of the term "declared globally special"? (CLTL uses the term pervasive", p158.) Anyway, assuming the above is true, then there is no need to worry that some constant might be "globally special", since you can't rebind one in any case. So my fix was to insert (not (constantp symbol)) at the appropriate spot. The only thing missing from this tidy explanation is why this hasn't happened to everyone else who's ever tried to load this system into common lisp. Kind of disquieting. IMHO, the difference between scheme and commonlisp is that scheme is only one language. Sean Burke "The nice thing about true hopelessness is that you don't have to try again" - Jules Shear