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