Defvar, setq, setf 
Author Message
 Defvar, setq, setf

Hi all
        I've been looking at a few tutorials but none has yet to
adequately describe the difference between the use of defvar and setq (I
understand that setf is basically setq with further functionality). E.g,
why, if at the beginning of my program I want to declare a list, should
I (defvar avariable '()) as opposed to (setq avariable '()). I have not
found an adequate description of the difference and they seem to do the
same thing.

                Andrew
--

===========================
      Andrew  Lawson

===========================



Tue, 12 Aug 2003 17:24:30 GMT  
 Defvar, setq, setf

Quote:

> Hi all
>         I've been looking at a few tutorials but none has yet to
> adequately describe the difference between the use of defvar and setq (I
> understand that setf is basically setq with further functionality). E.g,
> why, if at the beginning of my program I want to declare a list, should
> I (defvar avariable '()) as opposed to (setq avariable '()). I have not
> found an adequate description of the difference and they seem to do the
> same thing.

You might add DEFPARAMETER to list in your question.

--



Tue, 12 Aug 2003 20:00:35 GMT  
 Defvar, setq, setf

Andrew>  E.g, why, if at the beginning of my program I want to declare
Andrew>  a list, should I (defvar avariable '()) as opposed to (setq
Andrew>  avariable '()).

DEFVARing globals considered a good style since it explicitly tells
the compiler which variables will you use that way, so that when you
mistype (setq avarriable '()), compiler can (and usually will) issue a
warning about avarriable being declared special.
Note also that spec explicitly states that DEFVAR creates a binding
and establishes variable, while SETQ merely sets assigns values to
variables.
Explicit declarations also have additional benefits, say, you can place
a documentation string. See the description of DEFVAR/DEFPARAMETER and
SETQ in the chapter 5.3 of HyperSpec.

--
  Eugene



Tue, 12 Aug 2003 19:52:34 GMT  
 Defvar, setq, setf

There are a couple of differences:

  (defvar variable '())

will globally proclaim VARIABLE to be SPECIAL, and then set its value to
'() only if VARIABLE is unbound.  If VARIABLE already has a value, then
the existing value is left unchanged.

  (setq variable '())

will always set VARIABLE to '(), but it will not proclaim VARIABLE to be
SPECIAL.

Also, SETQ can be used inside a program, whereas DEFVAR is generally
used only at the top level.  I don't recall offhand whether this is a
requirement or not and I'm going to be too lazy to look it up.

Background:
  A special variable is one which has dynamic bindings rather than
lexical bindings.

Also, I recall seeing comments on this board that in CMUCL if you use
SETQ at top level it will globally proclaim it special (and issue an
appropriate warning).

--



Wed, 13 Aug 2003 09:01:18 GMT  
 Defvar, setq, setf


Quote:
>   (setq variable '())

> will always set VARIABLE to '(), but it will not proclaim VARIABLE to be
> SPECIAL.

Oddly enough, after perusing the HyperSpec, the documentation on setq says
that is asigns a value to the variable and can be used with either dynamic
or lexical variables.  Oddly enough, the spec (as far as I could see) says
nothing about setq's ability to establish bindings or what type of binding
is established.  Nor do the sections on environments detail the operators
that establish bindings.  Finally, the section on evaluation of symbol forms
is also quite vague and gives no help.  Could it actually be legal for the
following code:

(let (a)
    (setq b 0))

to
a) Return an error condition because there is no value available to write
(after all, no global, dynamic, or lexical binding is required to be created
by setq);
or
b) Have no effect, since the implementation of setq is allowed to create a
lexical binding rather than a global binding?

Granted, if your implementation did any of these thing, quite a bit of code
would break, but standards aren't about common sense, they're about
specificity...

faa



Wed, 13 Aug 2003 23:58:48 GMT  
 Defvar, setq, setf

Quote:



> >   (setq variable '())

> > will always set VARIABLE to '(), but it will not proclaim VARIABLE to be
> > SPECIAL.

> Oddly enough, after perusing the HyperSpec, the documentation on setq says
> that is asigns a value to the variable and can be used with either dynamic
> or lexical variables.  Oddly enough, the spec (as far as I could see) says
> nothing about setq's ability to establish bindings or what type of binding
> is established.

That's because SETQ does not establish bindings.  It changes a binding.
So you are not to use it at top-level except for something previously
established to be a special *if* you want to be conforming.  That leaves
it to the implementation whether it wants to only have global specials
(as CMU CL does) or whether it wants to define a new kind of thing called
a global lexical (like Scheme has, and over which you might create closures),
or whether you want to just do something clumsy and ad hoc (like most
implementations do, treating SETQ of a global as SETF of the SYMBOL-VALUE,
which doesn't really address the issue of whether a binding has been created
or not).

The spec leaves room for implementors to experiment with things that might
want to go into future specs.  Though admittedly this makes it a pain to
write good examples in documentation, since often DEFVAR is overkill and
LET is visually clumsy, and SETQ is semantically incorrect.



Thu, 14 Aug 2003 00:20:11 GMT  
 Defvar, setq, setf
[ Kent M Pitman ]

Quote:
> That's because SETQ does not establish bindings.  It changes a binding.
> So you are not to use it at top-level except for something previously
> established to be a special *if* you want to be conforming.  That leaves
> it to the implementation whether it wants to only have global specials
> (as CMU CL does) or whether it wants to define a new kind of thing called
> a global lexical (like Scheme has, and over which you might create closures),
> or whether you want to just do something clumsy and ad hoc (like most
> implementations do, treating SETQ of a global as SETF of the SYMBOL-VALUE,
> which doesn't really address the issue of whether a binding has been created
> or not).

I'm currenty reading Graham's On Lisp, and am just through with his
implementation of continuations in Common Lisp. There, on page 267, he
uses setq instead of defvar for as he writes (on p. 268): "That's why
*cont* is given its initial value in a setq instead of a defvar: the
latter would also proclaim it to be special".

It seems to me from this thread that his example would break in CMUCL.
Is this the right interpretation? On Lisp uses CLtL2, is there
differences in this respect between CLtL2 and the standard?

Martin
--
"An ideal world is left as an exercise to the reader."
                                                 -Paul Graham, On Lisp



Fri, 15 Aug 2003 22:09:55 GMT  
 Defvar, setq, setf

Quote:

>There are a couple of differences:

>  (defvar variable '())

>will globally proclaim VARIABLE to be SPECIAL, and then set its value to
>'() only if VARIABLE is unbound.  If VARIABLE already has a value, then
>the existing value is left unchanged.

>  (setq variable '())

>will always set VARIABLE to '(), but it will not proclaim VARIABLE to be
>SPECIAL.

What difference does it make to proclaim a variable as special?

g

 -----  Posted via NewsOne.Net: Free (anonymous) Usenet News via the Web  -----
  http://newsone.net/ -- Free reading and anonymous posting to 60,000+ groups
   NewsOne.Net prohibits users from posting spam.  If this or other posts



Fri, 15 Aug 2003 22:55:11 GMT  
 Defvar, setq, setf

Quote:

> [ Kent M Pitman ]

> > That's because SETQ does not establish bindings.  It changes a
> > binding.  So you are not to use it at top-level except for
> > something previously established to be a special *if* you want to
> > be conforming.  That leaves it to the implementation whether it
> > wants to only have global specials (as CMU CL does) or whether it
> > wants to define a new kind of thing called a global lexical (like
> > Scheme has, and over which you might create closures), or whether
> > you want to just do something clumsy and ad hoc (like most
> > implementations do, treating SETQ of a global as SETF of the
> > SYMBOL-VALUE, which doesn't really address the issue of whether a
> > binding has been created or not).

> I'm currenty reading Graham's On Lisp, and am just through with his
> implementation of continuations in Common Lisp. There, on page 267, he
> uses setq instead of defvar for as he writes (on p. 268): "That's why
> *cont* is given its initial value in a setq instead of a defvar: the
> latter would also proclaim it to be special".

I think the way most Lisp book writers think about it is that they are
giving examples of code without always showing the context.  For example,
the same SETQ is valid embedded in code that has bound the relevant value;
and, for debugging, most implementations will tolerate the SETQ at top-level
in a way that enables debugging of same.

Quote:
> It seems to me from this thread that his example would break in CMUCL.

Yes, but it's important to know that this is because of his example, and
not CMUCL.  The langauge gives CMUCL the right to do what it does, even
though tradition of implementation is not on their side and personally
I wish they would not have done it.

Quote:
> Is this the right interpretation?

CMUCL is technically right and Graham is technically wrong.

Though in practice I think a lot of people would say the ANSI CL spec is
wrong for not nailing this down, and that it should have nailed it down
in a way that made Graham right and CMUCL wrong.  Even the spec itself
probably has lots of examples that use the same style as Graham does,
though the spec disclaims all of its examples as "not binding on the
language definition" so gets out of harm's way by a "legal dodge".

Quote:
> On Lisp uses CLtL2, is there differences in this respect between CLtL2
> and the standard?

Shouldn't be.  This detail of how the top-level of Lisp works goes back to
CLTL1, I'm pretty sure.  Lack of agreement among vendors led to simply not
saying what the top-level treatment of undeclared symbols was.  The earlier
you go back (to 1980 or so, I mean, when the CL effort started), the more
you see vendors trying to reserve syntactic space to explore alternatives
to what CL was busy nailing down.  I think there was an unspoken early fear
up until 1984 (CLTL publication date) and even a year or two after that
CL might be "not right" or "not accepted" and vendors wanted to reserve the
right to dig themselves out of the problem while still being technically
compatible.  Post 1986, even though there were some nits to pick with CLTL,
CLTL was really widely accepted and there started to be a large convergence
on a lot of issues as people started to port programs and the needs of the
portable program to get an equal foothold dominated design concerns.  It is
really remarkable, I think, that this detail was never fixed as part of
that process.  Probably it was because CMUCL came later and wasn't in the
way of most big porting projects.  I personally submitted a very large number
of cleanup issues, most based on problems of porting Macsyma, and CMUCL
was not a porting target for Macsyma, so that explains why I didn't cite it
in my wishlist.  What others were using as their primary criteria, I can't
say.


Fri, 15 Aug 2003 23:48:22 GMT  
 Defvar, setq, setf

Quote:

> What difference does it make to proclaim a variable as special?

There is no undeclare/unproclaim facility.  So if you do

 (PROCLAIM '(SPECIAL FOO))                ;Don't try this at home

then later doing

 (LET ((FOO 3)) #'(LAMBDA () FOO))

will both special-bind FOO to 3 and then return a closure that is not closed
over that FOO because FOO is special, not lexical.

The only [portable] "fix" is to (UNINTERN 'FOO).

This is, among other things, a strong reason to put *...*'s around your
specials, so you don't later regret having used a name specially because
you want to use it lexically.

Note that this is different than a declaration.  Doing:

 (LET ((BAR 3))
   (DECLARE (SPECIAL BAR))
   (SETQ BAR 4))

doesn't mean that any subsequent uses of BAR have to be special.  Indeed,
you can even use BAR non-specially inside the same contour since the
declaration doesn't apply to new bindings created in that scope.

 (LET ((BAR 3)) ;special BAR
   (DECLARE (SPECIAL BAR))
   (LET ((BAR 4)) ;lexical BAR
     (LIST BAR (LOCALLY (DECLARE (SPECIAL BAR)) BAR))))

 => (4 3)

By contrast

 (PROCLAIM '(SPECIAL *BAR*))
 (LET ((*BAR* 3))
   (DECLARE (SPECIAL *BAR*)) ;redundant - the proclaim did this already
   (LET ((*BAR* 4))
     ;*BAR* here is special, too - the proclaim did this already
     (LIST *BAR* (LOCALLY (DECLARE (SPECIAL *BAR*)) *BAR*))))

 => (4 4)

This is because PROCLAIM makes a "pervasive" declaration--one that applies
even into new bindings.  You can't escape the scope of that declaration
like you can with a DECLARE.



Sat, 16 Aug 2003 01:20:00 GMT  
 Defvar, setq, setf

Quote:
> > It seems to me from this thread that his example would break in CMUCL.

> Yes, but it's important to know that this is because of his example, and
> not CMUCL.  The langauge gives CMUCL the right to do what it does, even
> though tradition of implementation is not on their side and personally
> I wish they would not have done it.

Note though that CMU CL gives you the choice which kind of behaviour
you want:

* (describe 'ext:*top-level-auto-declare*)

*TOP-LEVEL-AUTO-DECLARE* is an external symbol in the EXTENSIONS package.
It is a special variable; its value is :WARN.
   WARN is an external symbol in the KEYWORD package.
   It is a constant; its value is :WARN.
Special documentation:
  This variable controls whether assignments to unknown variables at top-level
   (or in any other call to EVAL of SETQ) will implicitly declare the variable
   SPECIAL.  These values are meaningful:
     :WARN  -- Print a warning, but declare the variable special (the default.)
      T     -- Quietly declare the variable special.
      NIL   -- Never declare the variable, giving warnings on each use.

If you set *top-level-auto-declare* to nil, you'll get the behaviour
Graham (and others) expect:

* (setq *top-level-auto-declare* nil)

NIL
* (setq d 4)

Warning: This variable is undefined:
  D

4
* (defun foo () d)

FOO
* (let ((d 5)) (foo))

In: LET ((D 5))
  (LET ((D 5))
    (FOO))
Note: Variable D defined but never used.

Warning: This variable is undefined:
  D

4

Quote:
> portable program to get an equal foothold dominated design concerns.  It is
> really remarkable, I think, that this detail was never fixed as part of
> that process.  Probably it was because CMUCL came later and wasn't in the
> way of most big porting projects.  I personally submitted a very large number
> of cleanup issues, most based on problems of porting Macsyma, and CMUCL
> was not a porting target for Macsyma, so that explains why I didn't cite it
> in my wishlist.  What others were using as their primary criteria, I can't
> say.

Hmmm, it was my understanding that CMU CL and its ancestors (Spice
Lisp, etc.) were in one form or another present since the beginnings
of the Common Lisp standardization process.

Regs, Pierre.

--

 The most likely way for the world to be destroyed, most experts agree,
 is by accident. That's where we come in; we're computer professionals.
 We cause accidents.                           -- Nathaniel Borenstein



Sat, 16 Aug 2003 06:49:22 GMT  
 
 [ 11 post ] 

 Relevant Pages 

1. SETQ vs DEFVAR at the top level

2. Defvar and setf 2

3. Defvar and setf

4. Naming of GET, SET, GETF, SETF, and SETQ.

5. setq setf

6. SET, SETQ, SETF confusion

7. setq x setf

8. setf & setq, newbie needs short definitions/examples

9. SETF vs. SETQ

10. What's the difference between setf, setq, defvar, defparameter, &c.?

11. &whole, defsetf, define-setf-method, define-setf-expansions, &environment and other Lispy Questions

12. CLHS - (redefining) setf expanders and DEFINE-SETF-METHOD

 

 
Powered by phpBB® Forum Software