From: kalh
Subject: Dumb newbie asks dumber question
Date: 
Message-ID: <3846D42F.3E6231A6@home.se>
Could someone explain why MCL said this to me:

? (setf foo 42)
42
? (setf bar 69)
69
? (psetf foo bar bar foo)
;Compiler warnings :
;   Undeclared free variable BAR (2 references), in an anonymous lambda form.
;   Undeclared free variable FOO (2 references), in an anonymous lambda form.
NIL
? foo
69
? bar
42

I don't understand what those warnings are about. How are the variables undeclared? 
This may be pointless, but I'm curious.

From: Christopher R. Barry
Subject: Re: Dumb newbie asks dumber question
Date: 
Message-ID: <87bt89krmi.fsf@2xtreme.net>
kalh <····@home.se> writes:

> Could someone explain why MCL said this to me:
> 
> ? (setf foo 42)
> 42
> ? (setf bar 69)
> 69
> ? (psetf foo bar bar foo)
> ;Compiler warnings :
> ;   Undeclared free variable BAR (2 references), in an anonymous lambda form.
> ;   Undeclared free variable FOO (2 references), in an anonymous lambda form.
> NIL
> ? foo
> 69
> ? bar
> 42
> 
> I don't understand what those warnings are about. How are the
> variables undeclared?

Those variables are undeclared because they are undeclared. SETF'ing
an undeclared variable at top-level in any Lisp (other than CMU CL)
just gives that variable a global value. The variable is not special:

  > (setf foo 42
	  bar 69)
  69

  > (defun foo-and-bar-values ()
      (list foo bar))
  FOO-AND-BAR-VALUES

  > (let ((foo 'not-42)
	  (bar 'not-69))
      (foo-and-bar-values))
  (42 69)


As you can see from above, FOO and BAR's dynamic bindings were not
modified, and their global values were used. This is because they are
not SPECIAL. Now let's make one of them special:

 > (declaim (special foo))
 NIL

  > (let ((foo 'not-42)
	  (bar 'not-69))
      (foo-and-bar-values))
  (NOT-42 69)


Since FOO is now declared special, the result above is different. Now
make BAR special:

  > (declaim (special bar))
  NIL

  > (let ((foo 'not-42)
	  (bar 'not-69))
      (foo-and-bar-values))
  (NOT-42 NOT-69)


If you do (DEFVAR FOO 42) instead of (SETF FOO 42), then FOO will be
declared SPECIAL automatically. Ordinarily, an interpreter does not
give the complaint that you got. MCL (AFAIK) however compiles every
form you type at top-level as a lambda-expression and then funcalls
it, so you get some of the same warning messages you would otherwise
only get with code compiled in a file.

Christopher
From: Larry Kramer
Subject: Re: Dumb newbie asks dumber question
Date: 
Message-ID: <3846F86A.43D93619@stsci.edu>
"Christopher R. Barry" wrote:
> 
> kalh <····@home.se> writes:
> 
> > Could someone explain why MCL said this to me:
> >
> > ? (setf foo 42)
> > 42
> > ? (setf bar 69)
> > 69
> > ? (psetf foo bar bar foo)
> > ;Compiler warnings :
> > ;   Undeclared free variable BAR (2 references), in an anonymous lambda form.
> > ;   Undeclared free variable FOO (2 references), in an anonymous lambda form.
> > NIL
> > ? foo
> > 69
> > ? bar
> > 42
> >
> > I don't understand what those warnings are about. How are the
> > variables undeclared?
> 
> Those variables are undeclared because they are undeclared. SETF'ing
> an undeclared variable at top-level in any Lisp (other than CMU CL)
> just gives that variable a global value. The variable is not special:

It shouldn't have to be declared special at the top-level, though, just
to do some quick exploratory tests.  But, you explain below why this is
so
*in MCL*, and I present (below) for kalh the example that he was
expecting to see.

> 
>   > (setf foo 42
>           bar 69)
>   69
> 
>   > (defun foo-and-bar-values ()
>       (list foo bar))
>   FOO-AND-BAR-VALUES
> 
>   > (let ((foo 'not-42)
>           (bar 'not-69))
>       (foo-and-bar-values))
>   (42 69)
> 
> As you can see from above, FOO and BAR's dynamic bindings were not
> modified, and their global values were used. This is because they are
> not SPECIAL. Now let's make one of them special:
> 
>  > (declaim (special foo))
>  NIL
> 
>   > (let ((foo 'not-42)
>           (bar 'not-69))
>       (foo-and-bar-values))
>   (NOT-42 69)
> 
> Since FOO is now declared special, the result above is different. Now
> make BAR special:
> 
>   > (declaim (special bar))
>   NIL
> 
>   > (let ((foo 'not-42)
>           (bar 'not-69))
>       (foo-and-bar-values))
>   (NOT-42 NOT-69)
> 
> If you do (DEFVAR FOO 42) instead of (SETF FOO 42), then FOO will be
> declared SPECIAL automatically. Ordinarily, an interpreter does not
> give the complaint that you got. MCL (AFAIK) however compiles every
> form you type at top-level as a lambda-expression and then funcalls
> it, so you get some of the same warning messages you would otherwise
> only get with code compiled in a file.

This was important to point out, and I almost didn't pick it up at the
bottom of your post.  I was very curious as to why compilation was going
on at the top-level.  In any Common Lisp I've worked with it is quite
reasonable to expect what kalh did to work and not complain.  This might
suggest that MCL may not be a good vehicle for someone to use who is
just
learning Lisp, as there are side affects going on at the top-level that
are not apparent to the novice.

Here's a snippet from an Allegro CL 5.0.1 top-level, that gives the
results
that I think kalh was expecting to see:

USER(13): (setf foo 42)
42
USER(14): (setf bar 69)
69
USER(15): (psetf foo bar bar foo)
NIL
USER(16): foo
69
USER(17): bar
42

To play with things at the top-level one shouldn't have to worry about
declarations for variables.

Larry

> 
> Christopher
From: Barry Margolin
Subject: Re: Dumb newbie asks dumber question
Date: 
Message-ID: <ONE14.27$4j4.1142@burlma1-snr2>
In article <·················@stsci.edu>,
Larry Kramer  <······@stsci.edu> wrote:
>"Christopher R. Barry" wrote:
>> 
>> kalh <····@home.se> writes:
>> 
>> > Could someone explain why MCL said this to me:
>> >
>> > ? (setf foo 42)
>> > 42
>> > ? (setf bar 69)
>> > 69
>> > ? (psetf foo bar bar foo)
>> > ;Compiler warnings :
>> > ;   Undeclared free variable BAR (2 references), in an anonymous lambda form.
>> > ;   Undeclared free variable FOO (2 references), in an anonymous lambda form.
>> > NIL
>> > ? foo
>> > 69
>> > ? bar
>> > 42
>> >
>> > I don't understand what those warnings are about. How are the
>> > variables undeclared?
>> 
>> Those variables are undeclared because they are undeclared. SETF'ing
>> an undeclared variable at top-level in any Lisp (other than CMU CL)
>> just gives that variable a global value. The variable is not special:
>
>It shouldn't have to be declared special at the top-level, though, just
>to do some quick exploratory tests.  But, you explain below why this is
>so
>*in MCL*, and I present (below) for kalh the example that he was
>expecting to see.

Some Lisps don't really have an interpreter, they compile everything.  So
when you're typing expressions at to the read-eval-print loop, they're
actually compiling each expression into a temporary function that they then
invoke (so it's actually a read-compile-call-print loop).  As a result,
something like:

(set foo 69)

is treated as if you'd done:

(defun temp-fun ()
  (setf foo 69))
(temp-fun)
(unintern 'temp-fun)

in Lisps that don't work this way.  The result is that you get warnings for
the expression just you would if it had been inside a function definition.

-- 
Barry Margolin, ······@bbnplanet.com
GTE Internetworking, Powered by BBN, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Christopher R. Barry
Subject: Re: Dumb newbie asks dumber question
Date: 
Message-ID: <87emd4eikh.fsf@2xtreme.net>
Larry Kramer <······@stsci.edu> writes:

> This was important to point out, and I almost didn't pick it up at the
> bottom of your post.  I was very curious as to why compilation was going
> on at the top-level.  In any Common Lisp I've worked with it is quite
> reasonable to expect what kalh did to work and not complain.  This might
> suggest that MCL may not be a good vehicle for someone to use who is
> just
> learning Lisp, as there are side affects going on at the top-level that
> are not apparent to the novice.
> 
> Here's a snippet from an Allegro CL 5.0.1 top-level, that gives the
> results
> that I think kalh was expecting to see:
> 
> USER(13): (setf foo 42)
> 42
> USER(14): (setf bar 69)
> 69
> USER(15): (psetf foo bar bar foo)
> NIL
> USER(16): foo
> 69
> USER(17): bar
> 42


Now watch this with ACL 5.0.1:

  USER(1): (loop
	     (format t "~&> ")
	     (print
	      (funcall (compile nil (coerce `(lambda () ,(read)) 'function)))))
  > (setf foo 42)
  ; While compiling (:ANONYMOUS-LAMBDA 3):
  Warning: Free reference to undeclared variable FOO assumed special.

  42 
  > (setf bar 69)
  ; While compiling (:ANONYMOUS-LAMBDA 4):
  Warning: Free reference to undeclared variable BAR assumed special.

  69 
  > (psetf foo bar bar foo)
  ; While compiling (:ANONYMOUS-LAMBDA 5):
  Warning: Free reference to undeclared variable BAR assumed special.
  Warning: Free reference to undeclared variable FOO assumed special.

  NIL 

If you switch pretty much any Lisp's interactive top-level to compile
instead of interpret then you get these kinds of warnings. 

> To play with things at the top-level one shouldn't have to worry about
> declarations for variables.

Well, you don't really need to worry about the declarations, but one
shouldn't be bothered with the warnings while just working
interactively with the top-level. Many Lisps have exported variables
in a COMPILER package or special WARN declarations that let you hush
this stuff up. MCL should by default not give these warnings for code
compiled in the interactive top-level. CMU CL also suffers from some
of this chattiness. (Though the declaring SPECIAL warning is sorta
important since other Lisps don't do that, but CMU CL ought to just be
like other Lisps in this respect....)

Christopher
From: Thomas A. Russ
Subject: Re: Dumb newbie asks dumber question
Date: 
Message-ID: <ymibt843qg6.fsf@sevak.isi.edu>
······@2xtreme.net (Christopher R. Barry) writes:

> Well, you don't really need to worry about the declarations, but one
> shouldn't be bothered with the warnings while just working
> interactively with the top-level. ...MCL should by default not give
> these warnings for code compiled in the interactive top-level.

I suppose that like many engineering decisions, this one also involves
tradeoffs.  While one might want to not have undeclared variable
warnings for some things typed at the top level, one might still want
them for function definitions that are typed in at the top level.  I
suppose the interpreter could distinguish between forms that begin with
(def...) and other forms, but I can see why they chose not to worry
about the issue -- most of the time it isn't a problem, because the
micro interpreter MCL has can handle the most common cases of evaluating
a variable value and setting it.


-- 
Thomas A. Russ,  USC/Information Sciences Institute          ···@isi.edu    
From: Tim Bradshaw
Subject: Re: Dumb newbie asks dumber question
Date: 
Message-ID: <ey3emd4s60r.fsf@lostwithiel.tfeb.org>
* Larry Kramer wrote:
> This was important to point out, and I almost didn't pick it up at the
> bottom of your post.  I was very curious as to why compilation was going
> on at the top-level.  In any Common Lisp I've worked with it is quite
> reasonable to expect what kalh did to work and not complain.  This might
> suggest that MCL may not be a good vehicle for someone to use who is
> just
> learning Lisp, as there are side affects going on at the top-level that
> are not apparent to the novice.

Unless I've misunderstood, there are no side-effects going on in MCL
that you wouldn't expect.  MCL is simply complaining more vigorously
than most implementations about undeclared variables because it seems
to be a compile-only system.

This is different than CMUCL where there *are* side-effects that you
might not expect (which it does warn about).

In CMUCL:


    * (setf foo 4)
    Warning:  Declaring foo special.

    4
    * (defun ft ()
    (let ((foo 5)) (fv)))

    ft
    * (defun fv () foo)

    fv
    * (ft) 

    5
    * 

--tim
From: Dave Seaman
Subject: Re: Dumb newbie asks dumber question
Date: 
Message-ID: <828lg9$9ig@seaman.cc.purdue.edu>
In article <···············@lostwithiel.tfeb.org>,
Tim Bradshaw  <···@tfeb.org> wrote:
>* Larry Kramer wrote:
>> This was important to point out, and I almost didn't pick it up at the
>> bottom of your post.  I was very curious as to why compilation was going
>> on at the top-level.  In any Common Lisp I've worked with it is quite
>> reasonable to expect what kalh did to work and not complain.  This might
>> suggest that MCL may not be a good vehicle for someone to use who is
>> just
>> learning Lisp, as there are side affects going on at the top-level that
>> are not apparent to the novice.

>Unless I've misunderstood, there are no side-effects going on in MCL
>that you wouldn't expect.  MCL is simply complaining more vigorously
>than most implementations about undeclared variables because it seems
>to be a compile-only system.

Compilation is not the issue.  In fact, you can configure MCL not to
compile definitions by doing a

	(setf *compile-definitions* nil)

or by setting this value in your preferences panel.  It doesn't make the
warning messages go away; it merely changes them from "compiler warnings"
to "interpreter warnings".  Doesn't the standard say that you should get
the same results whether you interpret or compile?

-- 
Dave Seaman			·······@purdue.edu
U.S. State Department Lies about Mumia Abu-Jamal
<http://mojo.calyx.net/~refuse/mumia/111999statedept.html>
From: William Deakin
Subject: Re: Dumb newbie asks dumber question
Date: 
Message-ID: <3847E3FD.87C49171@pindar.com>
Dave Seaman wrote:

> Doesn't the standard say that you should get the same results whether you
> interpret or compile?

Which standard?

Best Regards,

:) will
From: Jeff Dalton
Subject: Further clarification on not so dumb question
Date: 
Message-ID: <x2d7silrew.fsf_-_@todday.aiai.ed.ac.uk>
(There's one other issue that I'll discuss separately.)

> Doesn't the [ANSI] standard say that you should get
> the same results whether you interpret or compile?

Not quite, especially when "results" includes error and warning
messages.  (Nor does it say you should get the same results no matter
what implementation you use.)  For instance, it's common (and legal)
for "undeclared" variables to be accepted silently by interpreters
but result in warnings from compilers.

The interpreter / compiler rules are somewhat complex, but in practive
it's not too hard to get a feel for how things work in whatever
implementation(s) you're using.

It's unfortunate, though, that MCL gives a message that will make
so little sense to programmers who do not yet have a very
sophisticated understanding of Lisp.  It said

  Undeclared free variable BAR (2 references), in an anonymous lambda form

when the user didn't type any anonymous lambda form at all.

It's been suggested that the system is doing something like this
behind the scenes:

  USER(1): (loop
	     (format t "~&> ")
	     (print
	      (funcall (compile nil (coerce `(lambda () ,(read)) 'function)))))
  > (setf foo 42)
  ; While compiling (:ANONYMOUS-LAMBDA 3):
  Warning: Free reference to undeclared variable FOO assumed special.

That's a very plausible suggestion.  However the original message
included the following dialogue:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
? (setf foo 42)
42
? (setf bar 69)
69
? (psetf foo bar bar foo)
;Compiler warnings :
;   Undeclared free variable BAR (2 references), in an anonymous lambda form.
;   Undeclared free variable FOO (2 references), in an anonymous lambda form.
NIL
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

If that's a correct transcript, there was no warning for the two
SETF forms, only for the PSETF.

One possibility is that the PSETF form above is macroexpanded into
something that involves an anonymous lambda (perhaps via expansion
into LET) but the SETFs are not.

Such differences in expansion are exactly what happens in GCL,
for instance.  (Though GCL doesn't produce the warnings.):

> (macroexpand-1 '(setf foo 42))
(SETQ FOO 42)
T

> (macroexpand-1 '(psetf foo bar bar foo))
(LET* ((#:G1066 BAR) (#:G1067 FOO))
  (SETQ FOO #:G1066)
  (SETQ BAR #:G1067)
  NIL)
T

It's also possible that LET* is implemented in a way that involves
expanding it into a call to an anonymous lambda.

-- jeff
From: Dave Seaman
Subject: Re: Further clarification on not so dumb question
Date: 
Message-ID: <82jjfe$ij4@seaman.cc.purdue.edu>
In article <·················@todday.aiai.ed.ac.uk>,
Jeff Dalton  <····@todday.aiai.ed.ac.uk> wrote:
>
>(There's one other issue that I'll discuss separately.)
>
>> Doesn't the [ANSI] standard say that you should get
>> the same results whether you interpret or compile?

I was being partly facetious when I wrote that, but it is true that MCL
gives almost the identical message whether you are compiling or not.

>It's been suggested that the system is doing something like this
>behind the scenes:
>
>  USER(1): (loop
>	     (format t "~&> ")
>	     (print
>	      (funcall (compile nil (coerce `(lambda () ,(read)) 'function)))))
>  > (setf foo 42)
>  ; While compiling (:ANONYMOUS-LAMBDA 3):
>  Warning: Free reference to undeclared variable FOO assumed special.

No, I don't think that is the explanation.

>One possibility is that the PSETF form above is macroexpanded into
>something that involves an anonymous lambda (perhaps via expansion
>into LET) but the SETFs are not.

Correct.  SETF is a macro that expands to SETQ, which is a special form.
PSETF, on the other hand, expands to a more complicated expression.

You can see this in MCL by selecting an expression in the listener and
typing ctrl-x ctrl-m to macroexpand in the listener.

This also explains why you get the same messages (at least in this case)
whether you compile or not.  Macroexpansion is macroexpansion.

-- 
Dave Seaman			·······@purdue.edu
U.S. State Department Lies about Mumia Abu-Jamal
<http://mojo.calyx.net/~refuse/mumia/111999statedept.html>
From: Raymond Toy
Subject: Top-level variables.  Was Re: Dumb newbie asks dumber question
Date: 
Message-ID: <4n4se0hp4l.fsf_-_@rtp.ericsson.se>
>>>>> "Christopher" == Christopher R Barry <······@2xtreme.net> writes:

    Christopher> Those variables are undeclared because they are
    Christopher> undeclared. SETF'ing an undeclared variable at
    Christopher> top-level in any Lisp (other than CMU CL) just gives
    Christopher> that variable a global value. The variable is not
    Christopher> special:

I know this came up before, and I just found that setting
*top-level-auto-declare* to NIL, turns off this behavior.  However,
now every time that variable is used, the compiler complains about
using an undefined variable, but still uses it anyway, with the
expected results.  (describe '<var>) says it's an undefined variable,
too. :-)

* (setf *top-level-auto-declare* nil)
* (setf global 42)

Warning: This variable is undefined:
  GLOBAL

* (describe 'global)
GLOBAL is an internal symbol in the COMMON-LISP-USER package.
It is a undefined variable; its value is 42.
* (let ((x 4)) (+ x global))

Warning: This variable is undefined:
  GLOBAL

46
*

I guess people expect the variable to be given a global value, and not
declared special.  

If this is right, perhaps we can persuade the CMUCL folks to make this
the default (and get rid of the warning about using an undefined
variable).

Ray
From: Jeff Dalton
Subject: The truth about special and global [re not so dumb question]
Date: 
Message-ID: <x2bt82lpp8.fsf_-_@todday.aiai.ed.ac.uk>
This is a somewhat subtle issue, but getting it right sometimes
matters.  In probably doesn't matter very much here, but it may
still be a good time to point out a few "picky" distinctions.

"Global" variables in Common Lisp are special.  They haven't been
declared or proclaimed special, but they are special nonetheless.

Moreover, when it comes to SPECIAL declarations, DECLARE
and PROCLAIM/DECLAIM are very different in their effects.

PROCLAIM and DECLAIM make the name special wherever it occurs.
DECLARE does not.  (This difference allows us to perform some
revealing experiments.)

DEFVAR *proclaims* the vairable special.

Now, ······@2xtreme.net (Christopher R. Barry) writes re the
following forms:

> > ? (setf foo 42)
> > ? (setf bar 69)
> > ? (psetf foo bar bar foo)

> Those variables are undeclared because they are undeclared. SETF'ing
> an undeclared variable at top-level in any Lisp (other than CMU CL)
> just gives that variable a global value. The variable is not special:

Strictly speaking, they are all special.  Those assignments change the
special/dynmic value of those variables.  That's why you can do this:

   (setf foo 42)

and then

   (locally (declare (special foo)) foo)

will return 42.

>   > (setf foo 42
> 	  bar 69)
>   69
> 
>   > (defun foo-and-bar-values ()
>       (list foo bar))
>   FOO-AND-BAR-VALUES
> 
>   > (let ((foo 'not-42)
> 	  (bar 'not-69))
>       (foo-and-bar-values))
>   (42 69)
> 
> As you can see from above, FOO and BAR's dynamic bindings were not
> modified, and their global values were used. This is because they are
> not SPECIAL. 

It's because those names have not been proclaimed special.  It
is therefore possible to have lexically scoped variables of the same
names, as well as the global variables.  The FOO and BAR in the LET
above are such lexical variables; hence they are not refs to the global
variables at all.

Consider the following example:

(setq x 1 y 2 z 3)

(defun f ()
  (let ((x 10) (y 20))
    (declare (special x))
    (list* x  ; special
           y  ; lexical
           z  ; "global"
           (locally (declare (special x y x))
             ;; Now look at them all as specials.
             (list x y z)))))(defun f ()

(f) will return (10 20 3 10 2 3).

[CMUCL complicates this, because it proclaims x, y, and z special
as soon as it sees the setq.  So you have to do this instead:

 (locally (declare (special x y x))
    (setq x 1 y 2 z 3))

]

> Now let's make one of them special:
> 
>  > (declaim (special foo))
>  NIL

That proclaims it special, which removes the possibility of having
lexically scoped variables of the same name.

-- jeff
From: Coby Beck
Subject: Re: Dumb newbie asks dumber question
Date: 
Message-ID: <944245009558@NewsSIEVE.cs.bonn.edu>
judging from all the interesting and informative responses, i guess it was
not such a dumb question, after all...  ; )

Coby

kalh <····@home.se> wrote in message ······················@home.se...
> Could someone explain why MCL said this to me:
>
> ? (setf foo 42)
> 42
> ? (setf bar 69)
> 69
> ? (psetf foo bar bar foo)
> ;Compiler warnings :
> ;   Undeclared free variable BAR (2 references), in an anonymous lambda
form.
> ;   Undeclared free variable FOO (2 references), in an anonymous lambda
form.
> NIL
> ? foo
> 69
> ? bar
> 42
>
> I don't understand what those warnings are about. How are the variables
undeclared?
> This may be pointless, but I'm curious.
From: Thomas A. Russ
Subject: Re: Dumb newbie asks dumber question
Date: 
Message-ID: <ymiemd34q4j.fsf@sevak.isi.edu>
kalh <····@home.se> writes:


> Could someone explain why MCL said this to me:
> 
> ? (setf foo 42)
> 42
> ? (setf bar 69)
> 69
> ? (psetf foo bar bar foo)
> ;Compiler warnings :
> ;   Undeclared free variable BAR (2 references), in an anonymous lambda form.
> ;   Undeclared free variable FOO (2 references), in an anonymous lambda form.
> NIL
> ? foo
> 69
> ? bar
> 42
> 
> I don't understand what those warnings are about.
> How are the variables undeclared? 

The variables are undeclared because there wasn't any declaration of the
variables before they were used as special variables.  To eliminate the
warnings you would need to do something like:

  (defvar foo)
  (defvar bar)

before you used the variables.  Now you may ask why you only got the
warnings when doing the PSETF call in the Listener and not the SETF
calls.  That is because MCL has a fairly light-weight interpreter.
There are certain simple forms that the interpreter knows how to
evaluate, among them SETQ and SETF and some other basic operations.

Anytime something that is more complicated (or even just uncommon) is
encountered by the evaluator, it calls the compiler to compile the code
and then the evaluator executes the compiled code.  It is the compiler
that produces the warnings.  You can get a similar warning by doing
something like:

(let ((x 4)) (setf foo x))

> This may be pointless, but I'm curious.

The evaluator doesn't check for undeclared free variables, but the
compiler does.  It's just a question about which part of the system ends
up doing the work.


-- 
Thomas A. Russ,  USC/Information Sciences Institute          ···@isi.edu