Idiot's guide to special variables take 2 
Author Message
 Idiot's guide to special variables take 2

Edi Weitz asked me to update my "Idiot's guide to special variables" for
his Common Lisp Cookbook page.  Before I sent him my draft I thought I'd
solicit some comments.  I'm particularly interested in hearing from
non-Lisp-experts (who are the target audience) to see if this makes any
sense to them.

Thanks,
Erann


--------

The Complete Idiot's Guide to Special Variables and Lexical Closures

By Erann Gat
November 2002

Variables

The intuitive concept of a variable is very straighforward: it's a
NAME that is associated with a VALUE.  The value of a variable can be
changed by ASSIGNING a new value to the variable, e.g.:

  {
    int x = 1;  Create a new variable named X with value 1
    x = 2;      Change the value of the variable named X to 2
  }

This is about as much as the typical C programmer knows about variables
because creating variables and assigning them are the only two things
you can do with variables in C.  But in Lisp, variables are a much richer
and more powerful concept.  And more complicated.

In C the name of a variable is not a first-class data object.  Because
of this, one usually does not distinguish in C between the name of a
variable and its value.  "X" usually means the same thing as "the value
of the variable named 'X'" because the value is all there is.  So pointing
out that "the value of the variable named 'X'" also means the same thing
as "the contents of the memory location associated with the name 'X'"
sounds unnecessarily pedantic.

In Lisp the value is not all there is.  The NAMES of variables are
first-class data objects called SYMBOLS, and the MEMORY LOCATIONS where
the values of variables are stored are pseudo-first-class entities
called BINDINGS.  (I call them pseudo-first-class because unlike true
first-class entities, bindings cannot be directly passed as arguments or
returned as values.)  Symbols and bindings actually exist in C too, but
they are hidden in the deep recesses of the compiler where most programmers
never see them.  In Lisp, symbols and bindings are made available to the
programmer as part of the language.  The result is flexibility and power
that most C programmers never dream of.  And, unfortunately, the result
is also often a great deal of confusion.  Hence this guide.

Symbols

We get into terminological trouble right away because the word "NAME"
is used in two different ways when discussing variables.  In Lisp, the
name of a variable is a symbol, and a symbol is a first-class data
object that has, among other things, a name which is a string of
characters.  So the name of a variable is a symbol, and the name of
a symbol is a string.  (And strings don't have names.)

Symbols are referred to by their names, but they are distinguished
from their names by omitting the double-quotes that are traditionally
used to denote strings.  So, for example, we refer to a symbol whose
name is "FOO" by writing FOO.

There is a Lisp function for creating symbols called MAKE-SYMBOL. For
example, (MAKE-SYMBOL "FOO") returns a symbol whose name is the string
"FOO". (There is also a function, SYMBOL-NAME, which is sort of the
opposite of make-symbol: given a symbol it returns the string that is
the symbol's name.)

If you try (make-symbol "FOO") you may be surprised to find that the
result is not FOO but #:FOO.  #:FOO is indeed a symbol whose name is
"FOO" so I haven't really lied to you, but clearly there is more going
on here than meets the eye.  To understand the difference between the
symbol FOO and the symbol #:FOO we have to take a brief digression from
our discussion of variables and talk about packages.

Packages

Different symbols can have the same name.  If you call (make-symbol
"FOO") twice you will get two distinct symbols both of which have the
name "FOO".  (In fact, it's possible to have two distinct symbols
whose names are EQ.)  Having two symbols that look identical but are
in fact different can be confusing, and so symbols are usually
collected together in aggregations called PACKAGES, which have the
useful property that they may not contain distinct symbols with the
same name.

Adding a symbol to a package is called INTERNING the symbol in the
package, and it's done with a function called INTERN.  INTERN works
kind of like MAKE-SYMBOL in that it takes a string as an argument and
returns a symbol whose name is that string. But unlike MAKE-SYMBOL,
two different calls to INTERN with the same name will return the SAME
symbol, not two different symbols with the same name.  That is:

(eq (make-symbol "FOO") (make-symbol "FOO")) --> NIL
(eq (intern "FOO") (intern "FOO")) --> T

A symbol can only be interned in one package at a time.  Symbols that
are not interned in any package are printed with a leading "#:" to
alert you to the fact that two of them may not be the same symbol even
though they look alike.

You can now forget most of this and just remember that whenever you
see FOO it means a symbol named "FOO", and that any time you see FOO
it's the same symbol.

Bindings

A BINDING is an association between a symbol and some other object.
(Strictly speaking, a binding is an associating between a *name*
and some other object.  Names in Common Lisp are usually symbols,
but in some circumstances can be strings.)

Common Lisp symbols can have many different kinds of bindings.
Strictly speaking, the association between a symbol and its name is a
binding, although it's not usually spoken of that way.  In addition to
its name (which must be a string) a symbol can be associated with a
VALUE (which can be any object) and a FUNCTION (which must be a
function object) and a PROPERTY LIST.  That is, a symbol has a value
binding, and a function binding, and a property list binding (and a
name binding).  Actually, symbols can have two different kinds of
value bindings.  But we're getting ahead of ourselves.

(N.B.  One of the major differences between Common Lisp and Scheme is
that Common Lisp symbols have all these bindings simultaneously, while
Scheme symbols only have one binding at a time: the value binding.)

If all this is too complicated and esoteric, just think of a binding
as a memory location where the value of a variable is stored.  The
important thing is that the same variable can have different bindings
at different times, which is to say, the value of a variable can be
stored in different memory locations at different times.  The phrase
"creating a binding for a variable" means the same thing as "allocating
a memory location in which to store the value of that variable."

The crucial thing to keep in mind is that there is a distinction
between a BINDING (the memory location where the value of a variable
is stored) and its CONTENTS (the value stored in that memory location).
The contents of a binding is often referred to as the "value" of the
binding (or the value of the variable), which can be confusing because
the "value of a binding" is a completely different thing from the "value
binding".  The standard uses the term "that which the binding denotes"
in order to avoid this confusion, but that's a bit pedantic for my
tastes.

Fortunately, the concept of special variables (which is the topic at hand
in case you'd forgotten) deals only with value bindings, so we can forget
about all the other bindings that exist in Common Lisp and just use the
term "binding" from here on out to mean "value binding".  The "value of
a binding" then means the "value of the value binding", that is, the
contents of the memory location where the value of the variable is stored.

To illustrate the difference between values and bindings, consider
the following code:

  (let ((x 1))    ; Establish a binding for the symbol X
    (print x)
    (let ((x 2))  ; Establish a second binding for X
      (print x)
      (setq x 3)  ; Change the value of the second binding
      (print x))
    (print x))    ; The value of the first binding is unchanged

This will print "1 2 3 1".  The SETQ changes the value of the second
(or inner) binding of X, not the first (or outer) binding.

Because talking about multiple bindings for the same symbol can get
confusing, I'm going to adopt the following notation: X*n means the
nth binding of symbol X.  Using this notation we can describe the
above code as follows: the first LET form establishes binding X*1.
The second LET form established binding X*2.  The SETQ changes the
value of X*2 but not X*1.

(Actually, LET establishes new bindings every time it is run, so
the first time you run the above code you get X*1 and X*2.  The second
time you get X*3 and X*4, and so on.  Some forms establish bindings at
compile time, not run time, so you get the same binding every time the
code is run.)

Scope

The SCOPE of a binding is the parts of the program from which a
binding is VISIBLE, that is, from which the value of the binding
can be accessed by referring to the symbol.  For example, the scope
of a binding established by a LET is the body of the LET, e.g.:

(defun foo()
  (let ((x 1) (y 2))         ; Establish binding X*1 and Y*1
    (foo x y)                ; X refers to binding X*1, Y refers to Y*1
    (let ((y 2) (z 3))       ; Establish binding Y*2 and Z*1
      (baz x y z))           ; Refers to X*1, Y*2 and Z*1.  Y*1 cannot be
                             ;   accessed here.  It is SHADOWED by Y*2.
   z)                       ; This does NOT refer to Z*1.  Z*1 is out of scope.

What about Z?  Z is what is referred to as a FREE VARIABLE.  It is a
variable which has no LEXICALLY APPARENT BINDING, that is, it has no binding
established by its surrounding code.  Normally this would mean that when
we call FOO we would get an error:

(foo) --> ERROR: Z is unbound

But we can create a binding for Z using, for example, the DEFVAR special
form:

(defvar z 3)  ; Establish binding Z*D1

Now FOO no longer generates an error:

(foo) --> 3   ; Refers to the value of Z*D1

Note that the binding established by DEFVAR ...

read more »



Thu, 28 Apr 2005 09:03:50 GMT  
 Idiot's guide to special variables take 2

Quote:

> Edi Weitz asked me to update my "Idiot's guide to special
> variables" for his Common Lisp Cookbook page.  Before I sent
> him my draft I thought I'd solicit some comments.  I'm
> particularly interested in hearing from non-Lisp-experts (who
> are the target audience) to see if this makes any sense to
> them.

I don't know if I still qualify as a non-Lisp-expert, but I'll
answer anyway :-) Very nice text -- just a few points:

Quote:
> Lexical versus dynamic scope

> Now consider the following code:

> (defvar z 1)
> (defun foo () z)  ; Establish binding Z*D1
> (defun baz ()
>   (let ((z 2))    ; Establish binding Z*2
>     (foo)))

> What does (BAZ) return?  Well, it returns the result of calling
> FOO, which returns the value of Z, but which one?  There are
> two different bindings of Z at this point - one established by
> the DEFVAR (Z*D1) and one established by the LET (Z*2).  Which
> binding is in scope when FOO is called from inside BAZ?  Does
> Z*2 shadow Z*D1 in the same way that Y*2 shadowed Y*1?

> The rule for LET bindings is that their scope is the body of
> the LET, but that can mean two different things.  It can mean
> the body of the LET as defined by the CODE, or the body of the
> LET as defined by the EXECUTION PATH.  The reference to Z is
> inside the body of the LET according to the execution path, but
> not according to the structure of the code (since the code for
> FOO is outside the code for BAZ).

> (Re-read the preceding paragraph until you're sure you
> understand it.  It's the key to understanding everything else.)

You are right, it is a bit hard to understand.  I think it would
be much easier to explain if you introduced the usual terms
``lexical and dynamical environment.  A closure (and a
function) is always called with two environments, the (current)
dynamical environment and the lexical environment at creation
time (of the closure) (which can still be updated because what
gets closed over is a set of bindings, not a set of values).  The
only thing left to understand is which is used for lookup, then.

Quote:
> In fact, it is actually impossible on a strict reading of the
> standard to create a dynamic binding for a symbol without
> turning it into a (globally) special variable.

Hmmm.  How would you call this:

CL-USER 50 > (defun foo (n)
               (declare (special x))
               (+ x n))
FOO

CL-USER 51 > (defun blark (x)
               (declare (special x))
               (foo 42))
BLARK

CL-USER 52 > (blark 7)
49

CL-USER 53 > (defun {*filter*} (x)
               (foo 42))
{*filter*}

CL-USER 54 > ({*filter*} 13)

Error: The variable X is unbound.
  1 (continue) Try evaluating X again.
  2 Return the value of :X instead.
  3 Specify a value to use this time instead of evaluating X.
  4 Specify a value to set X to.
  5 (abort) Return to level 0.
  6 Return to top loop level 0.

Type :b for backtrace, :c <option number> to proceed,  or :? for other options

CL-USER 55 : 1 >

Quote:
> Now when we call (baz) we get back a function object (created
> by the LAMBDA special form).

LAMBDA is actually not a special form in Common Lisp.

Regards,
--
Nils G?sche
Ask not for whom the <CONTROL-G> tolls.

PGP key ID #xD26EF2A0



Thu, 28 Apr 2005 10:36:47 GMT  
 Idiot's guide to special variables take 2

Quote:

> > In fact, it is actually impossible on a strict reading of the
> > standard to create a dynamic binding for a symbol without
> > turning it into a (globally) special variable.

> Hmmm.  How would you call this:

Doh!  I meant to say "global binding" (or maybe "top-level binding").

Actually, I'm not really sure even that is true any more.  The standard
specifically says (parenthetically) that you can do (setf symbol-value) on
an unbound symbol without raising an exception (though the standard is
silent on what the effect of this ought to be).

E.



Thu, 28 Apr 2005 10:56:14 GMT  
 Idiot's guide to special variables take 2

Quote:


> > > In fact, it is actually impossible on a strict reading of the
> > > standard to create a dynamic binding for a symbol without
> > > turning it into a (globally) special variable.

> > Hmmm.  How would you call this:

> Doh!  I meant to say "global binding" (or maybe "top-level
> binding").

> Actually, I'm not really sure even that is true any more.  The
> standard specifically says (parenthetically) that you can do
> (setf symbol-value) on an unbound symbol without raising an
> exception (though the standard is silent on what the effect of
> this ought to be).

It is explicitly undefined behavior by 1.4.4.3: If you read
carefully the dictionary entry of (SETF SYMBOL-VALUE), you'll
notice a little restriction:

# Arguments and Values:

# symbol---a symbol that must have a value.

This refers to (SETF SYMBOL-FUNCTION), too.

As for the question whether we can ``create a global binding
without turning it into a (globally) special variable -- the
answer is yes: DEFCONSTANT :-) Otherwise there is simply no
defined way to create such a global binding without making it
dynamic:

``3.1.2.1.1 Symbols as Forms says that when a symbol that is
not a symbol-macro is evaluated, then it names a variable, which
is either lexical, dynamic or constant.  We are not interested in
a constant or dynamic binding, which leaves only a ``lexical
global binding as a possibility.  There is no such thing,
though, by definition: Lexical scope is always restricted to an
establishing form.

If you /do/ set the SYMBOL-VALUE of a symbol that is not yet in
the global environment, you can probably evaluate it afterwards,
so it must be a dynamic variable now, as we have just seen.  So,
now, for this to make sense, (SETF SYMBOL-VALUE) would have to
check, every time it is called, whether our symbol names a
variable in the global environment, and if not, put it in there.
If nobody kept track of what in the global environment is,
/every/ symbol would be part of the global environment, and,
because we don't want them all to be constants, /every/ symbol
would be the name of a dynamic variable!

I guess this is why it's undefined behavior.  Hm, still a lot of
food for thought :-)

Regards,
--
Nils G?sche
Ask not for whom the <CONTROL-G> tolls.

PGP key ID #xD26EF2A0



Thu, 28 Apr 2005 14:53:46 GMT  
 Idiot's guide to special variables take 2

Quote:

> This refers to (SETF SYMBOL-FUNCTION), too.

Err, actually it refers to (SETF SYMBOL-VALUE), too.

Sorry,
--
Nils G?sche
Ask not for whom the <CONTROL-G> tolls.

PGP key ID #xD26EF2A0



Thu, 28 Apr 2005 15:08:33 GMT  
 Idiot's guide to special variables take 2
After a hint by Paul Foley, I changed my mind...

Quote:


> > > > In fact, it is actually impossible on a strict reading of the
> > > > standard to create a dynamic binding for a symbol without
> > > > turning it into a (globally) special variable.
> > I meant to say "global binding" (or maybe "top-level
> > binding").
> > Actually, I'm not really sure even that is true any more.
> > The standard specifically says (parenthetically) that you can
> > do (setf symbol-value) on an unbound symbol without raising
> > an exception (though the standard is silent on what the
> > effect of this ought to be).

> It is explicitly undefined behavior by 1.4.4.3: If you read
> carefully the dictionary entry of (SETF SYMBOL-VALUE), you'll
> notice a little restriction:

> # Arguments and Values:

> # symbol---a symbol that must have a value.

> This refers to (SETF SYMBOL-[VALUE]), too.

Which appears to be just an oversight (see SET).

Quote:
> As for the question whether we can ``create a global binding
> without turning it into a (globally) special variable -- the
> answer is yes: DEFCONSTANT :-) Otherwise there is simply no
> defined way to create such a global binding without making it
> dynamic:

> ``3.1.2.1.1 Symbols as Forms says that when a symbol that is
> not a symbol-macro is evaluated, then it names a variable, which
> is either lexical, dynamic or constant.  We are not interested in
> a constant or dynamic binding, which leaves only a ``lexical
> global binding as a possibility.  There is no such thing,
> though, by definition: Lexical scope is always restricted to an
> establishing form.

And here is where I erred: There /is/ a global lexical
environment; it is called the null lexical environment, and it is
here where the binding is established.  This is not exactly made
explicit somewhere but there seems to be no other possible
interpretation.  Comments in Notes sections like ``set cannot
change the value of a lexical variable. notwithstanding.

Regards,
--
Nils G?sche
Ask not for whom the <CONTROL-G> tolls.

PGP key ID #xD26EF2A0



Fri, 29 Apr 2005 02:40:44 GMT  
 Idiot's guide to special variables take 2

| Edi Weitz asked me to update my "Idiot's guide to special variables" for
| his Common Lisp Cookbook page.  Before I sent him my draft I thought I'd
| solicit some comments.  I'm particularly interested in hearing from
| non-Lisp-experts (who are the target audience) to see if this makes any
| sense to them.

Well, I consider myself a non-Lisp-expert, but hopefully not the
complete idiot that you're targeting (if I can take your title at face
value).


I'm afraid I will have to decline, partly because I read news off-line
(and responding by email is therefore somewhat painful) but more
importantly, because I think it would be useful if some /real/ experts
were to comment on my comments.

I have only two brief comments really:

Firstly, I think the discussion of symbols and packages belongs
elsewhere.  It really doesn't help understanding to get that mixed in
with the whole lexical vs dynamic issue.  In other words, make this
guide into two separate guides, and it will work much better.

Secondly, aren't you falling into the common trap of confusing scope
and extent?  To my limited understanding, the scope of a variable is
the part of the source code in which the variable is visible.  A
lexical variable is visible only within the block in which it is
bound, whereas a special variable is visible everywhere, except where
it is shadowed by a lexical variable (and you can get around even that
restriction by using symbol-value).  On the other hand, the extent of
a special variable (or binding) is the set of times during the
execution when the binding is in effect, which is all the time from
the time it is first bound until execution leaves the binding form,
with the exception of the times when this binding is shadowed by other
bindings.

It seems that the Glossary section of the CLHS agrees with me on this
point.  Maybe it is difficult for beginners to make this distinction,
but I think it should not be that hard to explain:  A set of points in
source code really is a very different concept from a set of times,
and I think you are doing your readers a disservice by mixing the two
together.

--
* Harald Hanche-Olsen     <URL:http://www.math.ntnu.no/~hanche/>
- Yes it works in practice - but does it work in theory?



Fri, 29 Apr 2005 02:36:42 GMT  
 Idiot's guide to special variables take 2

Quote:

> Edi Weitz asked me to update my "Idiot's guide to special variables" for
> his Common Lisp Cookbook page.  Before I sent him my draft I thought I'd
> solicit some comments.  I'm particularly interested in hearing from
> non-Lisp-experts (who are the target audience) to see if this makes any
> sense to them.

  It's a good paper. I've always been confused with special variables,
  now it's clear.

  Thanx.

--
Frederic Brunel

"You can't rush art."



Mon, 02 May 2005 20:44:25 GMT  
 Idiot's guide to special variables take 2

Quote:

> Symbols

I'm still a bit confused about the meaning of "NAME", it would be good
if you could produce a concise definition.

Quotes from you:

1. In Lisp the value is not all there is.  The NAMES of variables are
   first-class data objects called SYMBOLS, and the MEMORY LOCATIONS
where

2. So the name of a variable is a symbol, and the name of
   a symbol is a string.  (And strings don't have names.)

3. Symbols are referred to by their names

4. A BINDING is an association between a symbol and some other object.
  (Strictly speaking, a binding is an associating between a *name*
   and some other object.  Names in Common Lisp are usually symbols,
   but in some circumstances can be strings.)

Especially quote 4 is confusing. If I combine 4 and 2, I can construct
the following sentence:
the name of a symbol is a string and names in CL are usually
symbols!???!?

I think you can avoid the whole complication in the following way:

A) In Lisp variables are called Symbols.

B) Each Symbol has an associated String, which is also used to refer
to it. This    is called the symbols name, accessible trought the
function symbol-name.

C) A BINDING is an association between a symbol and some other object.

I think this eliminated the confusion which was caused by defining a
symbol as the "name" of a variable.

Quote:
> Now consider:

> (dlet ((z 1))
>   (llet ((z 2))
>     z))

> or

> (llet ((z 1))
>   (dlet ((z 2))
>     z))

My first reaction when I saw this code, was that the inner binding
would always overshadow the outer one. This is because from the
viewpoint of an idiot a symbol can only have ONE value binding. I
think you should make clear that a symbol can have TWO(or maybe more?)
value bindings. Then the examples become immediately clear.

Quote:
> Common Lisp's LET combines the functionality of both LLET and DLET.  Variable
> references can be either lexical or dynamic depending on the context.  And
> there is a DVAR (called SYMBOL-VALUE) but no LVAR.

I think you misspelled: you mean DVAL and LVAL, right?
As an idiot I don't know the exact function definition of
SYMBOL-VALUE, so I had to look it up in the language specification. It
helped me to read its definition  where it explicitly says that "it
returns the current value of the dynamic variable named by symbol".
After that I could understand your examples much better. General rule
of thumb: always define something before making use of it.

Quote:
> Most implementations assume that since there are no lexically apparent
> bindings at the top level, that any top-level assignment is intended to
> modify the dynamic binding, and so they will create one for you automatically
> if you do a SETQ without a DEFVAR.

So that means in the following example:

 (setq x 1)
 (defun baz () x)
 (defun foo ()
   (let ((x 2))  ; Bind X, no special declaration means it's lexical,
but...
     (baz)))

If I call (foo) it will return 1 on most Lisps, but if I use CMUCL it
will return 2 right?

Hope I could help you to improve the writing... I have also learned a
lot by reading it, thank you!



Tue, 03 May 2005 08:37:16 GMT  
 Idiot's guide to special variables take 2

| A) In Lisp variables are called Symbols.

  This is in fact wrong.

| I think this eliminated the confusion which was caused by defining a
| symbol as the "name" of a variable.

  You have reintroduced the confusion.

| Hope I could help you to improve the writing... I have also learned a
| lot by reading it, thank you!

  I fail to see what was wrong or lacking in the description in CLtL 1 or 2
  or in the standard.  In my view, Erann's confused expression can only
  make things worse if you are already confused.  As has been shown.

--
Erik Naggum, Oslo, Norway

Act from reason, and failure makes you rethink and study harder.
Act from faith, and failure makes you blame someone and push harder.



Tue, 03 May 2005 08:44:33 GMT  
 Idiot's guide to special variables take 2

Quote:

>   I fail to see what was wrong or lacking in the description in CLtL 1 or 2
>   or in the standard.

Some of the standard's text is less than illuminating for beginners.  For
example, if you look up "dynamic variable" you will find this:

dynamic variable n. a variable the binding for which is in the dynamic
environment.

dynamic binding n. a binding in a dynamic environment.

dynamic environment n. that part of an environment that contains bindings
with dynamic extent. A dynamic environment contains, among other things:
exit points
established by unwind-protect, and bindings of dynamic variables, exit
points established by catch, condition handlers, and restarts.

dynamic extent n. an extent whose duration is bounded by points of
establishment and disestablishment within the execution of a particular
form. See indefinite extent. ``Dynamic variable bindings have dynamic
extent.''

If you think this is all perfectly clear then more power to you.  My guide
is not for you.

E.



Tue, 03 May 2005 09:21:02 GMT  
 Idiot's guide to special variables take 2

Quote:

> Especially quote 4 is confusing. If I combine 4 and 2, I can construct
> the following sentence:
> the name of a symbol is a string and names in CL are usually
> symbols!???!?

Yes, that's how it is.  The word "name" is used in two different ways in
the Common Lisp spec:

 binding n. an association between a name and that which the name denotes.

 symbol-name returns the name of symbol.  (symbol-name 'temp) =>  "TEMP"

Maybe I should refer to the name of a variable (which is a symbol) and the
symbol-name of a symbol (which is a string)?  I'm not sure that makes it
any less confusing.

Quote:
> I think you can avoid the whole complication in the following way:

> A) In Lisp variables are called Symbols.

But they aren't.  Variables and symbols are two different things.

E.



Tue, 03 May 2005 09:40:44 GMT  
 Idiot's guide to special variables take 2
* Erann Gat
| If you think this is all perfectly clear then more power to you.  My
| guide is not for you.

  Understanding is an emergent property.  If you seek to understand, reading
  the whole standard with the express purpose of listening to someone else
  and their ideas, is not foreign to you.  If you do not seek to understand,
  a very good way to avoid it is to expect to have everything explained just
  for you.

  Your "guide" is not for people who seek to understand, but for those who
  seek to avoid the effort it takes.  In this regard, it succeeds.

--
Erik Naggum, Oslo, Norway

Act from reason, and failure makes you rethink and study harder.
Act from faith, and failure makes you blame someone and push harder.



Tue, 03 May 2005 10:55:30 GMT  
 Idiot's guide to special variables take 2

Quote:

> Maybe I should refer to the name of a variable (which is a
> symbol) and the symbol-name of a symbol (which is a string)?
> I'm not sure that makes it any less confusing.

Certainly not :->

You are in a situation all teachers experience every now and
then: Either you continue telling your students a nice fairy tale
about the world, or you give up and tell them the whole story.
It is hard to tell which is the right way -- for some people one
way is better, for some people the other.  People like Erik, for
instance, (and me, too, at that), would be seriously offended if
they found out that you simplified things for them just for
pedagogical reasons.  You never know beforehand.  I still think
your text is good (and will be even better if you mention
environments as I proposed), but it should be clear that it is
only meant as a ``ladder to the /real/ thing -- I think reading
standards is simply easier if you already know more or less what
they are trying to tell you.  (But, of course, this presupposes
that you are aware of the fact that your knowledge is incomplete
and you'll have to change your mind about a few things).

Regards,
--
Nils G?sche
Ask not for whom the <CONTROL-G> tolls.

PGP key ID #xD26EF2A0



Tue, 03 May 2005 11:03:04 GMT  
 Idiot's guide to special variables take 2

Quote:

> A) In Lisp variables are called Symbols.

Incorrect.  Symbols are objects which have a name string, among other
properties.  Symbols are commonly, but not always, gathered into a table
which is keyed by the symbol's name.  The purpose of doing this (called
``interning'') is so that every successive use of the symbol's name
refers to the same exact (EQ) object.

Compare (eq (make-symbol "FOO") (make-symbol "FOO"))
and (eq (intern "BAR") (intern "BAR"))

MAKE-SYMBOL creates a symbol object without interning it.

However, symbols are used as the /names/ of lexical variables.  Consider
the following example:

(let ((a 1)) a)

Here the symbol A is used as the /name/ of a lexical variable.  This is
orthogonal to the matter of symbols having associated values.  For
example:

(intern "A")
(setf (symbol-value 'a) 0)
(let ((a 1)) (values a (symbol-value 'a)))

 ==> 1 0

As you can see, the value of the lexical variable A has nothing to do
with the symbol-value of the symbol A.

When the lexical variable A is evaluated, its binding is looked up in
the lexical environment by name.  The lexical environment is a table of
bindings, a table of names associated to values, that are visible in the
current lexical scope.

Quote:
> [...]
> So that means in the following example:

>  (setq x 1)
>  (defun baz () x)
>  (defun foo ()
>    (let ((x 2))  ; Bind X, no special declaration means it's lexical,
> but...
>      (baz)))

> If I call (foo) it will return 1 on most Lisps, but if I use CMUCL it
> will return 2 right?

If a top-level SETQ of an unbound variable is treated like a DEFVAR of
that variable, then that variable will be globally SPECIAL.  So using
LET will always establish a dynamic binding with such a variable.

Consider typical SPECIAL variables such as *PRINT-BASE*.  You do not
have to declare them SPECIAL every time you bind them.  

This is why there is an established convention for SPECIAL variable
names, using the *'s.

--

; OpenPGP public key: C24B6010 on keyring.debian.org
; Signed or encrypted mail welcome.
; "There is no dark side of the moon really; matter of fact, it's all dark."



Tue, 03 May 2005 12:33:11 GMT  
 
 [ 132 post ]  Go to page: [1] [2] [3] [4] [5] [6] [7] [8] [9]

 Relevant Pages 

1. The complete idiot's guide to special variables

2. Idiot's guide to special variables now available (again)

3. Idiot's Guide to Ada?

4. Idiot's guide to packages

5. Summary: 'special variables' in ST

6. Idiots guide to LISP!

7. Idiots guide to regexp/regsub?

8. idiots guide to python

9. tcl2c - Idiots guide needed

10. I admit - I'm an idiot (was OpenClipper Suggestion)

11. I'm an idiot, sombody help me...

 

 
Powered by phpBB® Forum Software