[Openmcl-devel] Compiler warnings

Taoufik Dachraoui taoufik.dachraoui at wanadoo.fr
Sun Oct 18 05:24:55 UTC 2009


I compared openmcl and cmucl and found that openmcl setf create a  
lexical variable
and mcucl setf create a dynamic variable

 >>> cmucl
* (setf d 2)

Warning:  Declaring D special.

2
* (defun f () (+ 1 d))

F
* (let ((d 5)) (f))

6
*

 >>> openmcl
? (setf d 2)
2
? (defun f () (+ 1 d))
;Compiler warnings :
;   In F: Undeclared free variable D
F
? (let ((d 5)) (f))
;Compiler warnings :
;   In an anonymous lambda form: Unused lexical variable D
3



This shows that setf is implemented differently; maybe it is  
interesting to compare
this with other implementations.


Another thing about the generated warning after POP when a variable is  
not defined
using DEFVAR or DEFPARAMETER.

taoufik-dachraouis-imac:ccl taoufik$ ccl
Welcome to Clozure Common Lisp Version 1.3-r11936  (DarwinX8632)!
? (setf lst '(1 2 3))
(1 2 3)
? (push 0 lst)
(0 1 2 3)
? (pop lst)
;Compiler warnings :
;   In an anonymous lambda form: Undeclared free variable LST (3  
references)
0
? (pprint (macroexpand-1 '(pop lst)))

(PROG1 (CAR LST) (SETQ LST (CDR (THE LIST LST))))
? (pprint (macroexpand-1 '(push 0 lst)))

(SETQ LST (CONS 0 LST))
?

In the macroexpansion of POP, unlike PUSH, declares LST to be a LIST  
(THE LIST LST).
It is THE that raises the warning. I find this inconsistent that PUSH  
does not declare
LST to be a list as in POP or may be both should not use specify the  
type of lst.

The CLHS describes THE as follows:

"the specifies that the values[1a] returned by form are of the types  
specified by value-type. The consequences are undefined if any result  
is not of the declared type."

It is clear that THE specifies the type of the returned values; I do  
not understand why THE
expects an expression if it is a symbol to be dynamic (special).

The following is to show that THE should not expect nor verify that a  
variable is dynamic
and that THE should use the returned values of the expression:

? (setf x 3)
3
? (the fixnum x)
;Compiler warnings :
;   In an anonymous lambda form: Undeclared free variable X
3
? (defun f () x)
;Compiler warnings :
;   In F: Undeclared free variable X
F
? (the fixnum (f))
3
? (the fixnum 3)
3
?


Also, according to the standard the consequence is undefined if any  
result of the expression
is not of the declared type. What should be undefined here? is it  
better to raise an error?

Taoufik


On Oct 18, 2009, at 1:44 AM, Taoufik Dachraoui wrote:

> Hi,
>
> I understand your explantion but what do you think about the  
> following:
>
> ? (setf lst '(1 2 3))
> (1 2 3)
> ? (push 0 lst)
> (0 1 2 3)
> ? lst
> (0 1 2 3)
> ? (pop lst)
> ;Compiler warnings :
> ;   In an anonymous lambda form: Undeclared free variable LST (3  
> references)
> 0
> ? (setf h (make-hash-table))
> #<HASH-TABLE :TEST EQL size 0/60 #x8F0E5F6>
> ? (setf (gethash :a h) 1)
> 1
> ? (gethash :a h)
> 1
> T
>
> No warning when using push and gethash
>
> Taoufik
>
>
> On Oct 16, 2009, at 9:56 PM, Gary Byers wrote:
>
>>
>>
>>
>> On Fri, 16 Oct 2009, David L. Rager wrote:
>>
>>> Hi Taoufik,
>>>
>>> You need to define x to avoid those warnings.
>>>
>>> (defvar *x* '(a b c))
>>>
>>> Note that I'm fairly sure that defvar only sets a variable's value
>>> upon initialization.  Any subsequent calls to define the same  
>>> variable
>>> are effectively no-ops.
>>
>> See also DEFPARAMETER.
>>
>>>
>>> IIRC, I think that if you're in a multi-threaded environment, not
>>> defining a variable causes the setf's to be thread-local.
>>
>> A (special) binding is basically a mapping between a special variable
>> name (a symbol) and a value.  One trivial and traditional way to
>> establish such a binding is to reserve a word in the symbol for
>> its global special value; this word is sometimes referred to as the
>> symbol's "value cell", and that binding is sometimes called a "static
>> binding".
>>
>> Things like LET/LET*/LAMBDA can establish new dynamic (and
>> thread-local) bindings for special variables.
>>
>> SETF/SETQ of a special variable always assign to the current thread's
>> current binding of that special variable.  The current binding is  
>> either
>> the most recently established (by LET/LET*/LAMBDA ...) dynamic  
>> binding
>> or the global static binding if the thread has no dynamic binding.
>>
>> Things like DEFVAR are usually used at toplevel (in the REPL or in a
>> file), and so any assignment that they do usually affects the global,
>> static binding.
>>
>> Back to the original poster's question: in something like:
>>
>> ? (setq x '(1 2 3))
>>
>> what exactly is X ?  Let's assume that:
>>
>> 1) it's not something proclaimed (via DEFCONSTANT) to be the name of
>>  a constant
>> 2) it's not something proclaimed (via DEFVAR, DEFPARAMETER, or other
>>  means) to be the name of a SPECIAL (dynamic) variable.
>> 3) it's not a lexical variable established by a surrounding LET/LET*/
>>  LAMBDA/... form that establishes lexical bindings.
>>
>> In portable CL, those are the only well-defined possibilities.  In
>> practice (and in most? all? implementations), there are at least two
>> other possibilities:
>>
>> 4) it's a reference/assignment to the "static binding" of X, e.g.,  
>> the
>>  "value cell of X", which is likely to be a meaningful concept.
>> 5) it's a typographical error or a symptom of one; it can be treated
>>  something like case (4), but is anomalous enough to be worth warning
>>  about.
>>
>> When compiling a file, it's desirable to treat references/assignments
>> to "undeclared free variables" (variables that don't fit into one of
>> the first 3 cases above) as being deserving of warnings.  Some people
>> habitually introduce "undeclared free variables" when typing
>> expressions to the REPL; some forms typed into the REPL in CCL are
>> handled by very simple evaluator (which generally doesn't try to warn
>> about this sort of thing); other forms are "evaluated" by compiling
>> them and funcalling the resulting function, and the compiler  
>> generally
>> does warn in this case.
>>
>> Some people have requested that warnings like this be suppressed in  
>> the
>> REPL.  I used to be more sympathetic to that than I am now (for  
>> whatever
>> reason);  I think that I've convinced myself that the small extra  
>> effort
>> involved in saying something like:
>>
>> ? (defvar *x* '(1 2 3))
>>
>> rather than
>>
>> ? (setq x '(1 2 3))
>>
>> even for something trival done in the REPL.  (Things that start out  
>> trivial
>> sometimes get at least a bit more complicated, actual typos get  
>> introduced,
>> and it starts to get hard to remember what "the convenience of not  
>> having
>> to use DEFVAR when you more-or-less meant to" was all about.)
>>
>> I guess that I'd agree that things should be consistent (and the  
>> simple
>> evaluator should warn in the same cases that the compiler does),  
>> but I
>> find it harder to agree that warnings should be suppressed: case  
>> (4) above
>> isn't all that well-defined and to the extent that pretending that  
>> it is
>> is a habit, that habit's breakable.
>>
>>>
>>> David
>>> _______________________________________________
>>> Openmcl-devel mailing list
>>> Openmcl-devel at clozure.com
>>> http://clozure.com/mailman/listinfo/openmcl-devel
>>>
>>>
>>
>

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.clozure.com/pipermail/openmcl-devel/attachments/20091018/5635e4d3/attachment.html>


More information about the Openmcl-devel mailing list