[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

annoying compiler warnings again



> >Date: Tue, 15 Jun 93 14:54:17 EDT
> >From: hall@research.att.com (Bob Hall)
> >To: bug-mcl@cambridge.apple.com
> >Cc: info-mcl@cambridge.apple.com
> >Subject: annoying compiler warnings again
> >
> >Is there some way to keep the
> >TIME macro from complaining about undeclared free variables in a top-level
> >expression?  This is annoying because, among other things, it switches me
> >to the listener window from whatever buffer holds the TIME form, and makes
> >me have to read the error message and figure out why it should be ignored.
> >
> >example:
> >? (setq test-text "Blah, blah, blah.")
>
>Just use 
>  (defvar test-text "Blah, blah, blah.") 
>instead.
>
>In general, use defvar and defparameter to introduce a variable,
>then just use setq (or setf) later. I know, it's a hard habit to 
>break, but it leads to better programming style in the long run.

Dear Steve, 

you probably know the side effects of defvar. I would like to add some 
comments just to make sure nobody misunderstands your message.

Using defvar (or defparameter) *globally* declares test-text to be special.
It is not merely a matter of programming style. There are indeed
semantic differences!

Please consider the following examples:

(defvar *test* 1)

(defun foo (f)
  (let ((*test* 2))
    (format t "~%This is test in foo: ~S" *test*)
    (funcall f)))

(foo #'(lambda () (format t "~%This is test in lambda: ~S" *test*)))

;;; This is test in foo: 2
;;; This is test in lambda: 2

;;; The same effects might happen when *test* is used (maybe accidentally)
;;; as a parameter name in some function like foo!
;;; Thus, the *...* notation is really useful for defvars.

;;; ************************************************************************


(setf another-test 1)

(defun bar (f)
  (let ((another-test 2))
    (format t "~%This is another-test in foo: ~S" another-test)
    (funcall f)))
    
(bar #'(lambda ()
         (format t "~%This is another-test in lambda: ~S" another-test)))

;;; With a warning.
;;; ;Compiler warnings :
;;; ;   Undeclared free variable ANOTHER-TEST, in an anonymous lambda form.
;;; This is another-test in foo: 2
;;; This is another-test in lambda: 1

(bar #'(lambda ()
         (declare (special another-test))
         (format t "~%This is another-test in lambda: ~S" another-test)))

;;; Same result, no warning.
;;; This is another-test in foo: 2
;;; This is another-test in lambda: 1

;;; ************************************************************************

(defun baz (f)
  (let ((another-test 2))
    (declare (special another-test))
    (format t "~%This is another-test in foo: ~S" another-test)
    (funcall f)))
    
(baz #'(lambda ()
         (format t "~%This is another-test in lambda: ~S" another-test)))

;;; Result:
;;; ;Compiler warnings :
;;; ;   Undeclared free variable ANOTHER-TEST, in an anonymous lambda form.
;;; This is another-test in foo: 2
;;; This is another-test in lambda: 2

(baz #'(lambda ()
         (declare (special another-test))
         (format t "~%This is another-test in lambda: ~S" another-test)))

;;; This is another-test in foo: 2
;;; This is another-test in lambda: 2

Best regards,

Ralf