Path: utzoo!utgpu!water!watmath!clyde!att!osu-cis!killer!ames!pasteur!ucbvax!decwrl!sun!pitstop!sundc!seismo!uunet!mcvax!ukc!etive!aiva!jeff
From: jeff@aiva.ed.ac.uk (Jeff Dalton)
Newsgroups: comp.lang.lisp
Subject: Re: SETQ vs DEFVAR at the top level
Message-ID: <496@aiva.ed.ac.uk>
Date: 10 Jul 88 20:30:08 GMT
References: <4431@medusa.cs.purdue.edu> <4434@medusa.cs.purdue.edu>
Reply-To: jeff@uk.ac.ed.aiva (Jeff Dalton)
Organization: Dept. of AI, Univ. of Edinburgh, UK
Lines: 165

In article <4434@medusa.cs.purdue.edu> bouma@cs.purdue.EDU (William J. Bouma) writes:
>The answer lies in that LET does a Dynamic shadowing of variables.
>That is, (LET ((X -3))) will only make a new binding of X if X is not dynamic
>in the calling environment. Otherwise it just gives the old binding of X a new
>value for the body of the LET clause.

>     Also, I still want to know if anyone has a way to force a new binding
>of a variable in front of making a closure. Is there a way to declare x to
>be non-special before the LET?

You might say that a LET always gives a new binding.  If you read the
description of LET in CLtL, you will see that it does not say lexical
variables are given new bindings while special variables are not.  All
it says is "each binding will be a lexical binding unless there is a
SPECIAL declaration to the contrary".

But since there is only one value of a special variable accessible at
a given time, the difference between having multiple bindings (but
only one visible) and having one binding (whose value changes, with a
way to change it back) may not seem that significant.  That it is not
significant, however, also means that it is not the source of your
problem.

What you want is a way to ensure a variable has lexical scope (so it
can be closed over).  Unfortunately, there is no way to do this in
Common Lisp: special proclamations cannot be shadowed, overridden, or
otherwise undone.

>Can anyone tell me why the CL designers chose to have LET behave in
>this manner?

Since it's not just LET that behaves this way, it's really the
semantics of special variables that you want explained.  The relevant
issues seem to be the following:

(1) Why do special proclamations pervasively affect bindings -- i.e.,
why does LET not automatically shadow special proclamations as it does
other special declarations?

The answer is indicated on page 158 of CLtL: for convenience and
compatibility with MacLisp.  Special proclamations let you make a
given identifier the name of a special variable everywhere.
Otherwise, to make *x* special everywhere you would need a
(declare (special *x*)) for every form that bound *x*.

The use of DEFVAR to proclaim variables special goes well with the
*name* convention, because it makes a special proclamation and hence
makes *name* special everywhere.

(2) Why is there no way to declare something lexical -- i.e., no way
override special proclamations and so guarantee that a variable is
lexical?

In part this may have been an oversight or an attempt to make the
language simpler (though asymmetric).  Moreover, it is unnecessary
if the *name* convention is actually followed.  If *name* always means
a special variable, you will never want to make such names nonspecial;
and no other names will ever be special.

(3) Why are special variables not included in closures?

Some Lisps have supported closures over the dynamic environment, but
generally with a high cost in efficiency or implementation complexity.

-----
>It seems like a lot of code I see just uses DEFVAR to declare all global
>variables as though that is what it is there for. In fact, I ran into this 
>problem because that is what I was doing without really thinking about it.
>I thought, and it sounds to me from reading this group that others think that
>one should always use DEFVAR to declare global variables.

What CLtL says about DEFVAR and style is that DEFVAR is the
recommended way to declare the use of a special variable (page 68)
or the conventional way to make a special proclamation (page 158).
It does not say DEFVAR is the correct way to declare global variables.
Indeed, Common Lisp does not require the declaration of global
variables at all.  You might even say Common Lisp does not have global
variables.  What it has is special variables, which may have global
values.

In any case, the *name* convention implies that *name* should always
be special (i.e., dynamically scoped).  The way to ensure that is to
proclaim such names special, and the recommended way to proclaim them
special is to use DEFVAR.

The problem with SETQ, then, is that it does not proclaim the variable
special.  If you merely (SETQ *X* 10) and then use *X* as a formal
parameter or in a LET, you will have a *X* that is not special.  So,
if you use the *name* convention, you will want to use DEFVAR.

Finally: you should use the *name* convention because it lets you
determine whether a variable is special (modulo spelling errors and
omitted DEFVARs) by local inspection.  Using SETQ and the *name*
convention, or abandoning the convention, might have some advantages,
but overall (or so the argument goes) would be worse.

In other words, there is a reason to use DEFVAR, but thinking of it in
terms of declaring global variables is probably more confusing than
enlightening.  (But see below.)

>Just recently I have read "setq does not make a binding" and "it may
>be bad style to make globals with setq".

In a sense, it is certainly true that SETQ does not make a binding
(while LET does).  When comparing with DEFVAR, however, the question
is top-level bindings.

If we consider a (special) variable without a value in the top-level
environment, CLtL is somewhat confusing.  On page 56, it says such a
variable is unbound "unless and until explicitly assigned a value",
implying that assignment (SETQ) will make it bound.  But it also says
the global value is the value "when there are currently no bindings".

In some other dialects of Lisp, the situation is clearer.  In T, for
example, DEFINE and LSET establish top-level bindings, and SET does
not: a SET when there is no binding is an error.

But the difficulty in Common Lisp really concerns how we should talk
about top-level values, not the difference between SETQ and DEFVAR.
When DEFVAR gives a value to a variable, it does so by assignment; and
assignment is what SETQ does.  So whatever they do about bindings,
DEFVAR and SETQ do the same thing.

What DEFVAR does that SETQ does not, except for possible "system-
dependent bookkeeping actions", is to proclaim the variable special.

>I now hold that it is safer to use SETQ to declare global variables
>because it can be hard to track down this type of error in your closures.

But, for other reasons, your strategy may be worse overall.  What
makes DEFVAR acceptably safe is the *name* convention.

>Does someone have problems with using SETQ thus?

Yes.  If you use SETQ instead of DEFVAR you will either have difficulty
using the *name* convention consistently (you will have to remember to put
in special declarations or adopt some macros that to so automatically) or
you will have to abandon the convention and so have difficulty keeping
track of which variables are special.

The exception would be if you use special variables only as global
variables and never give them a value except the top level one.
(Perhaps this is all you have ever had in mind, and if so I apologize
for the misunderstanding.)  This is often done in other languages, but
then they give you no choice.  It is less often done in Lisp because
one usually wants to give a special variable a value only temporarily.
That is, one wants to take advantage dynamic scope and not just to use
global variables.

-----
A better explanation of these points can be obtained by adopting some
consistent terminology that makes it clear just what is meant by
"variable", "binding", and so on.  For this, you might look at the
Scheme report or Gabriel and Pitman's "Technical Issues of Separation
in Function Cells and Value Cells" in the first issue of Lisp and
Symbolic Computation.  To follow the details of Common Lisp, you may
have to read the following sections of CLtL:
  * Chapter 3: Scope and Extent
  * Chapter 5: Program Structure, sections 5.1.2 and 5.3.2
  * Chapter 7: Control Structure, sections 7.1.1 and 7.1.2
  * Chapter 9: Declarations

Jeff Dalton,                      JANET: J.Dalton@uk.ac.ed             
AI Applications Institute,        ARPA:  J.Dalton%uk.ac.ed@nss.cs.ucl.ac.uk
Edinburgh University.             UUCP:  ...!ukc!ed.ac.uk!J.Dalton