From: Erann Gat
Subject: Idiot's guide to special variables take 2
Date: 
Message-ID: <gat-0911021704350001@192.168.1.51>
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

Please send comments by email if possible to ···@jpl.nasa.gov.

--------

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 seems to be of a fundamentally
different nature than a binding established by LET.  Bindings established
by LET go away when the LET form returns.  By constrast, a binding established
by DEFVAR continues to exist after the DEFVAR returns.  Also, whether
a particular reference to Z refers to the binding established by DEFVAR
depends on the order in which the code runs: if the reference to Z
happens before the defvar then it's a error.  If it happens afterwards,
then it refers to the binding established by the DEFVAR.

DEFVAR does in fact establish a different sort of binding, known as
a DYNAMIC binding, which is why I referred to it as Z*D1 instead of just
Z*1.  But we're getting ahead of ourselves again.


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.)

It turns out that you have a choice.  Common Lisp provides both
scoping disciplines.  If the scope is defined by the execution path
that is known as DYNAMIC SCOPE.  If the scope is defined by the
structure of the code that is known as LEXICAL SCOPE.

(Note that the lexical scope of a binding can always be determined at
compile time, while the dynamic scope cannot in general be determined
until the program runs.  If that is not obvious to you at this point,
go back and re-read this section again.)

How do you choose?  Unfortunately, this is yet another point where things get
a little complicated.  In order to ease into the explanation I'm going to
first illustrate with a hypothetical language that doesn't really exist
(though you can implement it in Common Lisp).  In this hypothetical language,
there are two LET forms, LLET and DLET.  LLET always introduced lexical
bindings (i.e. bindings whose scope is the lexical body of the LLET) and
DLET always introduces dynamic bindings (that is, bindings whose scope is
*any* code that runs inside the body of the DLET regardless of where it is
defined).  For example:

(defvar z 1)      ; Establish binding Z*D1
(defun foo () z)  ; Return the current dynamic binding of Z
(llet ((z 2))     ; Create Z*1, a lexical binding
  (foo)) --> 1    ;   which does not shadow Z*D1
(dlet ((z 2))     ; Create Z*D2
  (foo)) --> 2    ;   which does shadow Z*D1

Now consider:

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

or

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

Now we have *two* bindings for Z, one lexical and one dynamic, in scope at the
same time.  Which one are we referring to?  Well, we could allow ourselves
to refer to both with hypothetical LVAL and DVAL constructs that allow us to
refer to the values of the lexical and dynamic bindings respectively:

(defvar z 1)      ; Establish binding Z*D1
(defun foo () z)  ; Z must refer to the current dynamic binding of Z because
                  ; there is no lexical binding
(d-let ((z 2))
  (llet ((z 3))
    ; Simply referring to Z here would be ambiguous
    (list (lval 'z)  ; The value of the current lexical binding of Z
          (dval 'z)  ; The value of the current dynamic binding of Z
          (foo)      ; and our old friend for good measure
          )))   --> (3 2 2)

Now the reality.

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.

By default, LET creates lexical bindings (i.e. bindings whose scope are
defined by the lexical structure of the code, not by the runtime execution).
To create a dynamic binding you have to use a special declaration:

(let ( (x 1) (y 2) )      ; Lexical bindings by default
  (declare (special x))   ;   unless you say otherwise
  ...)

In Common Lisp, SPECIAL and dynamic mean the same thing.

So, for example:

(defun baz ()
  (let ( (x 2) )
    (list x (symbol-value 'x))))  ; Same as (list (lval 'x) (dval 'x))

(defun foo ()
  (let ( (x 1) )             ; Bind X
    (declare (special x))    ;   ... as a dynamic binding
    (baz)))

(foo) --> (2 1)

What happens when we call FOO is that we establish a dynamic binding
for X with value 1.  We then call BAZ, which establishes a lexical binding
for X with value 2.  The reference to X by itself returns the value of
the lexical binding, while SYMBOL-VALUE gives us access to the dynamic
binding.

The evils of DEFVAR

There is one more wrinkle.  Consider:

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

Based on what I've told you so far you should expect (foo) to return 1.  But
in fact (foo) returns 2.  Why?  Becase DEFVAR does more than just establish
a dynamic binding for X.  It pervasively declares all references to X and
all subsequent bindings for X to be dynamic (or special -- same thing).  In
other words, DEFVAR turns X (permanently and pervasively) into a special
variable.

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.  This is why in many Lisp implementations if you type
(SETQ X 1) without a DEFVAR you will get a warning.  Strictly speaking,
SETQ does assignment, that is, it modifies a binding (a symbol's value binding
to be precise).  But at the top level a symbol doesn't *have* a value
binding until you create one, e.g. with DEFVAR.

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.  But at least one implementation (CMUCL)
goes further: if you do a SETQ at the top level it will not only create a
dynamic binding for that symbol, but it will also globally declare that
symbol to be special just as if you had done a DEFVAR.  This can lead to
very surprising behavior if you don't have a deep understanding of what is
going on.  Once a symbol has been DEFVARd it is no longer possible to
create a lexical binding for it.

Some people consider this a feature.  Others (myself included) think it's
a bug.  Regardless, there is universal agreement that it can cause
confusion, and so there is a convention that is invariably followed: all
special variables should have names that are preceded and followed by
asterisks, e.g. *X*.

(Editorial comment: IMO, if you're going to have the concept of
a pervasively special variable and acknowledges that a typographical
convention is necessary in order to avoid confusion, then you ought
to build that typographical convention into the language design.  It
should be the case that all variables whose names start with an asterisk
are automatically declared special, and all names that don't start with
an asterisk are automatically lexical.)

By the way, it is also possible to have top-level (or global) lexical
bindings for symbols.  This is what Scheme does.  Scheme gets away with
this because *all* bindings in Scheme are lexical; there are no dynamic
bindings.  Top-level lexicals could in theory be added to Common Lisp,
but you'd have to figure out how to make them co-exist with dynamic
bindings.  (There have been designs proposed in the past.)

Lexical closures

Since we've now covered everything you need to know to understand
lexical closures we might as well go ahead and talk about them.

Consider:

(defun foo ()
  (let ((x 1))   ; Create a (lexical) binding for X
    x            ; X is in scope here
    ))           ; X goes out of scope here

FOO returns the value of X, not the binding.  It is not possible to
return a binding because bindings are not first-class entities.
However, it is possible to "capture" a binding inside of a function
object and return *that* instead!  Consider:

(defun baz ()
  (let ((x 1))                     ; Create a (lexical) binding for X
     (lambda () (setq x (+ x 1)))  ; X is in scope here
     ))

Now when we call (baz) we get back a function object (created by the
LAMBDA special form).  This function object has a reference to X inside
it which refers to the lexical binding created by the LET.

Note that I haven't followed my usual pattern and given this binding
the name X*1.  This is because a new binding is created every time BAZ
is called:

(setq *x1* (baz)) ; Returns a closure over binding X*1
(setq *x2* (baz)) ; Returns a closure over binding X*2
(funcall *x1*) --> 2  ; Increment X*1
(funcall *x1*) --> 3  ; again
(funcall *x1*) --> 4  ; one more time
(funcall *x2*) --> 2  ; Increment X*2

One last example:

(defun up-n-down ()
  (let ((x 0))
    (list (lambda () (setq x (+ x 1)))
          (lambda () (setq x (- x 1))))))

(setq *l1* (up-n-down))        ; X bound to X*1
(setq *l2* (up-n-down))        ; X bound to X*2
(funcall (first *l1*)) --> 1
(funcall (first *l1*)) --> 2
(funcall (first *l1*)) --> 3
(funcall (second *l1*)) --> 2
(funcall (first *l2*)) --> 1
(funcall (first *l2*)) --> 2
(funcall (first *l2*)) --> 3
(funcall (second *l2*)) --> 2

By now this should all make perfect sense.  When we call up-n-down we
get a new binding for X (established by the LET).  This binding is then
captured by the LAMBDA forms.  Both lambdas in the list capture the
*same* binding every time up-n-down is called, and every time we call
up-n-down we get a (one) new binding.

Notice how much the list returned by up-n-down resembles an object with
one slot and two methods.  That is in fact precisely what it is.  This is
why when a Lisp programmer learns a new programming language one of the
first questions they will ask is, "does it have closures?"  Because if
you have closures you can build an OO system (and just about anything
else you need) out of them.  It is, alas, much harder to go the other
way.

From: Nils Goesche
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <873cqarw00.fsf@darkstar.cartan>
···@jpl.nasa.gov (Erann Gat) writes:

> 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:

> 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.

> 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 bimbo (x)
               (foo 42))
BIMBO

CL-USER 54 > (bimbo 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 > 

> 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
From: Erann Gat
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <gat-0911021857000001@192.168.1.51>
In article <··············@darkstar.cartan>, Nils Goesche <···@cartan.de> wrote:

> > 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.
From: Nils Goesche
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <87smy9ykxx.fsf@darkstar.cartan>
···@jpl.nasa.gov (Erann Gat) writes:

> In article <··············@darkstar.cartan>, Nils Goesche <···@cartan.de> wrote:
> 
> > > 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
From: Nils Goesche
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <87of8xyk9a.fsf@darkstar.cartan>
I <···@cartan.de> wrote:

> 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
From: Nils Goesche
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <87d6pd5kur.fsf@darkstar.cartan>
After a hint by Paul Foley, I changed my mind...

I <···@cartan.de> wrote:

> ···@jpl.nasa.gov (Erann Gat) writes:
> 
> > > > 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).

> 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
From: Pekka P. Pirinen
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <u7kfeu064.fsf@globalgraphics.com>
> > ···@jpl.nasa.gov (Erann Gat) writes:
> > > > > 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").

I'm not sure what you intend by that "globally" in parentheses.
Ignoring it, it's saying global bindings must be dynamic; As Nils
G�sche pointed out, this ignored constant variables, but it's true
otherwise.  Reading that as "globally special", it's not true: you can
have a global binding without the variable being globally special:

(locally
  (declare (special x))
  (setq x 1))

You might say that can't be called a top-level binding, since the form
that refers to it is not a top-level form, but OTOH, it's certainly
the top binding, there can't be another one outside it.

Nils G�sche <···@cartan.de> writes:
> > ``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.

I think "the null lexical environment" is a descriptive phrase, not a
definite reference; it doesn't mean there's just one such environment.
See remarks in the glossary entry for "null" (just above the entry for
"null lexical environment") about how "the null string" is used in
preference to the technically more correct "a null string".

Furthermore, "null" means there aren't any in it, so one can hardly
say a binding is established there.

There are no global lexical bindings.  Even granting the possibility,
you'd need a way to establish one, and none is provided.
-- 
Pekka P. Pirinen
Mail should be private, whether on paper or on disk.  Public gatherings
should be a right, whether virtual or in person.
From: Nils Goesche
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <lku1iiv5or.fsf@cartan.de>
···············@globalgraphics.com (Pekka P. Pirinen) writes:

> Nils G�sche <···@cartan.de> writes:

> > > ``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.

> I think "the null lexical environment" is a descriptive phrase, not
> a definite reference; it doesn't mean there's just one such
> environment.

I think its meaning is given by

3.1.1.3.1 The Null Lexical Environment

and

3.1.1.1 The Global Environment

> See remarks in the glossary entry for "null" (just above the entry
> for "null lexical environment") about how "the null string" is used
> in preference to the technically more correct "a null string".
> 
> Furthermore, "null" means there aren't any in it, so one can hardly
> say a binding is established there.

Heh.  Well, we are talking about evaluation contexts; ``null�� might
mean ``no more bindings than usual (in the global environment)��.

> There are no global lexical bindings.  Even granting the
> possibility, you'd need a way to establish one, and none is
> provided.

How about (setf (symbol-value 'foo) 42)? :-)

Regards,
-- 
Nils G�sche
"Don't ask for whom the <CTRL-G> tolls."

PGP key ID 0x0655CFA0
From: Erik Naggum
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <3246412315069073@naggum.no>
* Nils Goesche
| 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 very confused.  The "null lexical environment" communicates to
  the alert reader that there are no lexically apparent bindings, not that
  any new bindings are established in it.  That `eval� is evaluated in the
  null lexical environment means that it cannot access lexically apparent
  bindings, which `eval� does not attempt to capture bindings when it
  receives a form.

  This is going off on a tangent, but assume you have a lexical environment
  with variables named `foo� and `bar�, and wish to evaluate an expression
  that references these bindings via the obvious mechanism, the symbols
  `foo� and `bar�, respectively -- how would you do that?  The association
  between symbol and variable is a compile-time-only notion for lexical
  bindings, and the lexical environment does not survive compilation.  If
  certain bindings have been captured by a closure, the association between
  symbol and variable is still lost and have to re-established explicitly.

  This is why, for instance, macro-expanding functions accept an environment
  and `eval� does not, and more importantly, could not, and why environments
  are not first-class objects but rather compile-time-only notions that have
  to be constructed and used opaquely.  The ability for macros to access the
  lexical environment of the caller therefore must be of a very different
  nature than the accessability of and to the global environment via special
  variables and value slots in symbols.

-- 
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.
From: Nils Goesche
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <87znsaauvd.fsf@darkstar.cartan>
Erik Naggum <····@naggum.no> writes:

> * Nils Goesche
> | 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 very confused.  The "null lexical environment"
>   communicates to the alert reader that there are no lexically
>   apparent bindings, not that any new bindings are established
>   in it.

Well, yes.  Maybe I shouldn't use the term ``null lexical
environment�� when talking about it.

>   That `eval� is evaluated in the null lexical environment
>   means that it cannot access lexically apparent bindings,
>   which `eval� does not attempt to capture bindings when it
>   receives a form.

Sure.  What I am trying to understand is the following:

CL-USER 30 > (eval 'most-positive-double-float)
1.7976931348623165E308

CL-USER 31 > (setf (symbol-value 'x) 42)
42

CL-USER 32 > (eval 'x)
42

There is indeed no lexically apparent binding for those two
symbols.  But their values are looked up somewhere, in an
environment.  Which is it?

The global environment, obviously, which is also called ``null
lexical environment�� to emphasize that it contains no lexically
apparent bindings (see 3.1.1.3.1 The Null Lexical Environment).
Neither MOST-POSITIVE-DOUBLE-FLOAT nor X have been declaimed
special, however.

Now, MOST-POSITIVE-DOUBLE-FLOAT is a constant, which is not so
interesting, but X is not.  I can do

CL-USER 33 > (setf (symbol-value 'x) 17)
17

CL-USER 34 > (eval 'x)
17

anytime I want.  I can also do

CL-USER 35 > (let ((x 13))
               (+ x 5))
18

I would also like to try the following:

(defun test (y)
  (+ x y))

(let ((x 20))
  (test 7))

Now, 3.2.2.3 Semantic Constraints says:

# Special proclamations for dynamic variables must be made in the
# compilation environment. Any binding for which there is no
# special declaration or proclamation in the compilation
# environment is treated by the compiler as a lexical binding.

But I might snottily claim that I don't want X to be special,
anyway :-)

But what the heck, let's do it anyway:

CL-USER 36 > (defun test (y)
               (+ x y))
Warning: Syntactic warning for form X:
   X assumed special.
TEST

CL-USER 37 > (let ((x 20))
               (test 7))
24

as expected.  

Whether this is legal code or not is not so interesting at the
moment; what I like is that we can explain everything that
happened in the above experiments without resorting to
implementation issues if we simply say that X is part of such a
thing as a ``global lexical environment��.  While this sounds a
bit like an oxymoron because lexical bindings are usually
lexically restricted to establishing forms and have dynamic
extent, it is well possible to give the term a reasonable
meaning.

Now, what happens if we do

CL-USER 38 > (declaim (special x))
NIL

CL-USER 39 > (let ((x 20))
               (test 7))
27

By globally declaring X special, we instruct the system to
perform the last binding in the dynamic environment, instead.  It
is rather puzzling that TEST already behaves accordingly, too!
So, now X is also part of the (global) dynamic environment,
obviously.  And it has kept its value :-)

Christian Queinnec writes in ``Lisp in Small Pieces�� (p. 50):

# In addition, if we do not find the dynamic value, then we go
# back to the global lexical environment, since it also serves as
# the global dynamic environment in Common Lisp.

> [split explanations]

Thank you for those, but I think I already understood this.  The
above is the point I am a bit confused about :-)

Note that my problem does not stem from confusing symbols with
variables.  My (SETF SYMBOL-VALUE) actions are one thing, not
very interesting; the interesting part is explaining the
evaluations, semantically.

All these considerations are certainly rather esoteric, idle
speculation.  What /really/ goes on under the hood in the
implementation is perfectly clear, anyway; but I find it
interesting, anyway.

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

PGP key ID #xD26EF2A0
From: Erik Naggum
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <3246463395155052@naggum.no>
* Nils Goesche
| The global environment, obviously, which is also called ``null
| lexical environment�� to emphasize that it contains no lexically
| apparent bindings (see 3.1.1.3.1 The Null Lexical Environment).

  No, this is not right.  That two things are the same in one respect does
  not make them the same in all respects, which they would have to be to be
  interchangeable.  It is like `not� and `null�.

| Whether this is legal code or not is not so interesting at the moment;
| what I like is that we can explain everything that happened in the above
| experiments without resorting to implementation issues if we simply say
| that X is part of such a thing as a ``global lexical environment��.

  But there is no such thing.  The whole point is that it is /not/ lexical.

| Christian Queinnec writes in ``Lisp in Small Pieces�� (p. 50):
| 
| # In addition, if we do not find the dynamic value, then we go
| # back to the global lexical environment, since it also serves as
| # the global dynamic environment in Common Lisp.

  I believe this is more accurate for Scheme.

| What /really/ goes on under the hood in the implementation is perfectly
| clear, anyway; but I find it interesting, anyway.

  When the implementation is clear and the concepts are not, the conceptual
  model is wrong.

-- 
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.
From: Nils Goesche
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <87wund5mr7.fsf@darkstar.cartan>
Erik Naggum <····@naggum.no> writes:

> * Nils Goesche

> | Christian Queinnec writes in ``Lisp in Small Pieces�� (p. 50):
> | 
> | # In addition, if we do not find the dynamic value, then we go
> | # back to the global lexical environment, since it also serves as
> | # the global dynamic environment in Common Lisp.
> 
>   I believe this is more accurate for Scheme.

Yes, probably.

> | What /really/ goes on under the hood in the implementation is
> | perfectly clear, anyway; but I find it interesting, anyway.
> 
>   When the implementation is clear and the concepts are not,
>   the conceptual model is wrong.

Heh, quite right.  I'll go think about it some more.

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

PGP key ID #xD26EF2A0
From: Aleksandr Skobelev
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <m33cq0edf9.fsf@list.ru>
Erik Naggum <····@naggum.no> writes:

> * Nils Goesche
> | The global environment, obviously, which is also called ``null
> | lexical environment�� to emphasize that it contains no lexically
> | apparent bindings (see 3.1.1.3.1 The Null Lexical Environment).
> 
>   No, this is not right.  That two things are the same in one respect does
>   not make them the same in all respects, which they would have to be to be
>   interchangeable.  It is like `not� and `null�.

Speaking frankly, I don't understand clearly what this phrase in 
`3.1.1.3.1 The Null Lexical Environment' means:

    "The null lexical environment is equivalent to the global
     environment."

What the equivalence do they speak about? Do they mean that, like the
global environment, the null lexical environment contains no lexical
bindings? Or it might be that they speak about an equivalency in a sense
of bindings for functions and macros and proclamations/declarations? I'm
confused. :(
From: Nils Goesche
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <87k7jcautp.fsf@darkstar.cartan>
Aleksandr Skobelev <···········@list.ru> writes:

> Erik Naggum <····@naggum.no> writes:
> 
> > * Nils Goesche
> > | The global environment, obviously, which is also called ``null
> > | lexical environment�� to emphasize that it contains no lexically
> > | apparent bindings (see 3.1.1.3.1 The Null Lexical Environment).
> > 
> >   No, this is not right.  That two things are the same in one
> >   respect does not make them the same in all respects, which
> >   they would have to be to be interchangeable.  It is like
> >   `not� and `null�.
> 
> Speaking frankly, I don't understand clearly what this phrase in 
> `3.1.1.3.1 The Null Lexical Environment' means:
> 
>     "The null lexical environment is equivalent to the global
>      environment."
> 
> What the equivalence do they speak about?

As I understand it, it means that whenever it says that a form is
evaluated in the null lexical environment, like the argument to
EVAL, for instance, it cannot access any lexically apparent
bindings.  The only bindings it /can/ access are those in the
global environment and the current dynamic environment, but /no/
lexical ones.

> Do they mean that, like the global environment, the null
> lexical environment contains no lexical bindings?

Yes.  I was only wondering about if it would make sense to
/introduce/ a notion of a global lexical binding when speaking
about Common Lisp to make it easier to explain some freaky code
snippets of questionable legal status.  But whatever it was I was
talking about it wasn't Common Lisp as defined by the HyperSpec.

> I'm confused. :(

I hope it wasn't me who caused that :-)

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

PGP key ID #xD26EF2A0
From: Rob Warnock
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <hc6dndMa84-IO0WgXTWcqg@giganews.com>
Nils Goesche  <···@cartan.de> wrote:
+---------------
| As I understand it, it means that whenever it says that a form is
| evaluated in the null lexical environment, like the argument to
| EVAL, for instance, it cannot access any lexically apparent
| bindings.  The only bindings it /can/ access are those in the
| global environment and the current dynamic environment, but /no/
| lexical ones.
+---------------

Well, it *can*, of course, access any new lexical bindings introduced
in the expression being EVAL'd, as well as any lexical bindings
previously closed over by functions called by the EVAL'd code. You
didn't really mean to exclude those when you said "/no/ lexical ones",
did you?

To me, to say that "a form is evaluated in the null lexical environment"
means that the *current* lexical environment is not accessible.


-Rob

-----
Rob Warnock, PP-ASEL-IA		<····@rpw3.org>
627 26th Avenue			<URL:http://www.rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Nils Goesche
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <lkheefufes.fsf@cartan.de>
····@rpw3.org (Rob Warnock) writes:

> Nils Goesche  <···@cartan.de> wrote:
> +---------------
> | As I understand it, it means that whenever it says that a form is
> | evaluated in the null lexical environment, like the argument to
> | EVAL, for instance, it cannot access any lexically apparent
> | bindings.  The only bindings it /can/ access are those in the
> | global environment and the current dynamic environment, but /no/
> | lexical ones.
> +---------------
> 
> Well, it *can*, of course, access any new lexical bindings
> introduced in the expression being EVAL'd, as well as any lexical
> bindings previously closed over by functions called by the EVAL'd
> code. You didn't really mean to exclude those when you said "/no/
> lexical ones", did you?

Of course not.  Maybe I should say ``any bindings lexically apparent
to EVAL where it is called��.

> To me, to say that "a form is evaluated in the null lexical
> environment" means that the *current* lexical environment is not
> accessible.

Of course.

Regards,
-- 
Nils G�sche
"Don't ask for whom the <CTRL-G> tolls."

PGP key ID 0x0655CFA0
From: Erik Naggum
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <3246632354249421@naggum.no>
* Rob Warnock
| Well, it *can*, of course, access any new lexical bindings introduced in
| the expression being EVAL'd, as well as any lexical bindings previously
| closed over by functions called by the EVAL'd code. You didn't really
| mean to exclude those when you said "/no/ lexical ones", did you?

  I fail to grasp what the problem is.  The function `eval� is no different
  from any other function.  That is the key.  No other function can access
  the caller's lexical environment, either.  WTF is so special about `eval�
  that it needs all this bogus attention?  Yes, you call a function that
  has captured some lexical bindings, but that does not change the fact
  that function /calls/ in Common Lisp do not, cannot, know anything about
  the caller's lexical environment.

-- 
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.
From: Kurt B. Kaiser
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <m3of8miqex.fsf@float.attbi.com>
Erik Naggum <····@naggum.no> writes:

>   The function `eval� is no different from any other function.  That
>   is the key.  No other function can access the caller's lexical
>   environment, either.  WTF is so special about `eval� that it needs
>   all this bogus attention?  Yes, you call a function that has
>   captured some lexical bindings, but that does not change the fact
>   that function /calls/ in Common Lisp do not, cannot, know anything
>   about the caller's lexical environment.

So the necessary parts of the calling function's environment must be
explicitly passed to the callee.  Hm.  Not your father's dynamic Lisp.  

Do people who are up to speed in CL use flet and labels when they can,
or do they tend to define everything at top level?

Is there an advantage to using flet instead of labels when the code
doesn't require using labels?

KBK
From: Tim Bradshaw
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <ey3k7jao5qu.fsf@cley.com>
* Kurt B Kaiser wrote:

> Do people who are up to speed in CL use flet and labels when they can,
> or do they tend to define everything at top level?

I use both quite a lot.  I often write (large) functions which are
actually a bundle of local functions which do the work.  They may (but
may not) use lexical bindings from the parent, but in any case all
those functions are only needed in one place, why define them
globally?

But my style is probably quite idiosyncratic - the resulting 50-300
line functions might make people queasy until they realise that they
are actually complete little worlds, like cheap packages...

> Is there an advantage to using flet instead of labels when the code
> doesn't require using labels?

Sometimes (not often) it requires FLET, for instance shadowing a
global (non-CL-defined) function (there are good uses for this,
honest!)

--tim (this article makes me sound like the worst kind of hacker...)
From: Larry Clapp
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <nuuera.lt.ln@rabbit.ddts.net>
In article <···············@cley.com>, Tim Bradshaw wrote:
> * Kurt B Kaiser wrote:
>> Do people who are up to speed in CL use flet and labels when
>> they can, or do they tend to define everything at top level?
> 
> I use both quite a lot.  I often write (large) functions which
> are actually a bundle of local functions which do the work.
<snip>
> --tim (this article makes me sound like the worst kind of
> hacker...)

Well, not to me, but it does remind me of the style I used
programming in Pascal.  Remembering the usefulness and elegance
of functions local to another function made me realize the point
of flet and labels.

-- Larry
From: Kurt B. Kaiser
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <m3y97qgwb8.fsf@float.attbi.com>
Erik Naggum <····@naggum.no> writes:

>   WTF is so special about `eval� that it needs all this bogus
>   attention?  Yes, you call a function that has captured some
>   lexical bindings, but that does not change the fact that function
>   /calls/ in Common Lisp do not, cannot, know anything about the
>   caller's lexical environment.

Actually, it is surprising to me (not being that familiar with CL)
that eval did not do its thing in the environment of the let.  I
looked it up, and now understand that it uses the global environment.
Why would it be designed that way?

KBK
From: Thomas F. Burdick
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <xcvof8mco55.fsf@famine.OCF.Berkeley.EDU>
···@shore.net (Kurt B. Kaiser) writes:

> Erik Naggum <····@naggum.no> writes:
> 
> >   WTF is so special about `eval� that it needs all this bogus
> >   attention?  Yes, you call a function that has captured some
> >   lexical bindings, but that does not change the fact that function
> >   /calls/ in Common Lisp do not, cannot, know anything about the
> >   caller's lexical environment.
> 
> Actually, it is surprising to me (not being that familiar with CL)
> that eval did not do its thing in the environment of the let.  I
> looked it up, and now understand that it uses the global environment.
> Why would it be designed that way?

Rather, ask why it wouldn't.  EVAL is just a function like any other.
It takes its argument, which it then interprets as CL code[*].  A
complete CL interpreter in CL only takes a few hundred lines of code,
after all, so there's no need for any magic.

If you could capture the current runtime lexical environment as an
object, then you could write a two-argument EVAL.  But that would have
horrible performance implications, for very little real benefit.

[*] It can "interpret" it by compiling, of course.

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | No to Imperialist war |                        
     ,--'    _,'   | Wage class war!       |                        
    /       /      `-----------------------'                        
   (   -.  |                               
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: Kenny Tilton
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <3DD9AE83.7040704@nyc.rr.com>
Kurt B. Kaiser wrote:
> Actually, it is surprising to me (not being that familiar with CL)
> that eval did not do its thing in the environment of the let.  I
> looked it up, and now understand that it uses the global environment.
> Why would it be designed that way?

 From the spec (3.8.4 eval):

"Examples:

  (setq form '(1+ a) a 999)  999
  (eval form)  1000
  (eval 'form)  (1+ A)
  (let ((a '(this would break if eval used local value))) (eval form))
  1000"

ie, dont think of eval as only being used for a literal form (if I am 
guessing correctly the source of your surprise).

-- 

  kenny tilton
  clinisys, inc
  ---------------------------------------------------------------
""Well, I've wrestled with reality for thirty-five years, Doctor,
   and I'm happy to state I finally won out over it.""
                                                   Elwood P. Dowd
From: Kurt B. Kaiser
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <m3n0o6gq5k.fsf@float.attbi.com>
Kenny Tilton <·······@nyc.rr.com> writes:

> Kurt B. Kaiser wrote:
> > Actually, it is surprising to me (not being that familiar with CL)
> > that eval did not do its thing in the environment of the let.  I
> > looked it up, and now understand that it uses the global environment.
> > Why would it be designed that way?
> 
>  From the spec (3.8.4 eval):
> 
> "Examples:
> 
>   (setq form '(1+ a) a 999)  999
>   (eval form)  1000
>   (eval 'form)  (1+ A)
>   (let ((a '(this would break if eval used local value))) (eval form))
>   1000"
> 
> ie, dont think of eval as only being used for a literal form (if I am
> guessing correctly the source of your surprise).

Hyperspec:

"Evaluates form in the current dynamic environment and the null
[i.e. empty] lexical environment."

ANSI CL (Graham):
"(eval expression) Evaluates expression in the global environment."

I was using the latter until I read your post.  To me, there is a 
difference, e.g. threads.

Hm. Using the dynamic environment makes more sense to me.

No, what surprised me was that the "lexical" x in the let didn't
shadow the prior dynamic x.

KBK
From: Erik Naggum
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <3246668724440113@naggum.no>
* Kurt B. Kaiser
| Actually, it is surprising to me (not being that familiar with CL) that
| eval did not do its thing in the environment of the let.  I looked it up,
| and now understand that it uses the global environment.  Why would it be
| designed that way?

  Because it is an ordinary function.

  I am genuinely puzzled: Why is this so hard to grasp?

-- 
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.
From: Kurt B. Kaiser
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <m3isyugkzf.fsf@float.attbi.com>
Erik Naggum <····@naggum.no> writes:

> * Kurt B. Kaiser
> | Actually, it is surprising to me (not being that familiar with CL) that
> | eval did not do its thing in the environment of the let.  I looked it up,
> | and now understand that it uses the global environment.  Why would it be
> | designed that way?
> 
>   Because it is an ordinary function.
> 
>   I am genuinely puzzled: Why is this so hard to grasp?

HyperSpec:
"Note that an eval form involves two levels of evaluation for its
argument. First, form is evaluated by the normal argument evaluation
mechanism as would occur with any call. The object that results from
this normal argument evaluation becomes the value of the form
parameter, and is then evaluated as part of the eval form. "

In light of this (especially the second sentence), and using
Skobelev's example from the other side of this thread,

----------
* (setf x 10)
Warning: This variable is undefined:
  X

10
* (let ((x 20))
    (declare (special x)) 
    (let ((x 30)) 
      (print x)
      (eval 'x)))
30 
20
* 
----------

I would have expected eval to evaluate its argument in the lexical
environment of the let block.  Other functions, like print, have their
arguments evaluated in that lexical environment before being passed.

However, the _effect_ of eval seems to be not quite like other
functions because when it evaluates its argument it does so in the
current dynamic environment, and that is definitely not what I was
expecting.  Maybe if it was called dynamic-eval I would have caught on
immediately.

* Eric Naggum
> "Now, if you make no lexical bindings on this fresh set of overlays,
> you have the null lexical environment.  This is what `eval starts
> out with, just like any other function before it makes its own
> lexical bindings, such as for incoming arguments (which may also
> cause special bindings, btw)."

You can think of it that way but isn't "null lexical environment" just
a fancy way of saying (and emphasizing) "no lexical environment?"  So,
attempting to extend your example for the case of eval, can one say the
dynamic overlay is flipped into place and the lexical overlay is not?
Can eval write on the "lexical overlay"?

On a slightly different, but closely related, subject, I find it
confusing that the `special declaration also "punches holes" in those
parts of the lexical overlay which were created after the last dynamic
binding, as in the example.  In this case, my intuition expected the x
in the let to shadow the dynamic binding, but clearly I'm getting an
intuition upgrade.

KBK
From: Erik Naggum
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <3246674834366592@naggum.no>
* Kurt B. Kaiser
| I would have expected eval to evaluate its argument in the lexical
| environment of the let block.

  But /why/?  When you quote x, you explicitly request that it /not/ be
  evaluated.  You pass `eval� a symbol, not a value from the lexical
  environment.  If you want the latter effect, do not quote x.

| Other functions, like print, have their arguments evaluated in that
| lexical environment before being passed.

  If you try `(print 'x)�, it will print `x�, not the value thereof.

| However, the _effect_ of eval seems to be not quite like other functions
| because when it evaluates its argument it does so in the current dynamic
| environment, and that is definitely not what I was expecting.

  All other functions do the same.  This is how function evaluation works.
  This is how the dynamic environment works.

| On a slightly different, but closely related, subject, I find it
| confusing that the `special declaration also "punches holes" in those
| parts of the lexical overlay which were created after the last dynamic
| binding, as in the example.

  I have no idea what this means.

  I believe you still think in a different language and are unwilling to
  let go of what you believe you understand.  Like perhaps `eval� in Perl.

-- 
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.
From: Kurt B. Kaiser
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <m37kfagior.fsf@float.attbi.com>
Erik Naggum <····@naggum.no> writes:

> * Kurt B. Kaiser
> | I would have expected eval to evaluate its argument in the lexical
> | environment of the let block.
> 
>   But /why/?  When you quote x, you explicitly request that it /not/ be
>   evaluated.  You pass `eval� a symbol, not a value from the lexical
>   environment.  If you want the latter effect, do not quote x.

The task of evaluating the arguments is passed to `eval, and it
proceeds to produce a different result than the "normal" evaluation
referred to in the HyperSpec.  That's the view from someone of limited
CL experience.  However, I think I'm getting it now.

[...]

> | On a slightly different, but closely related, subject, I find it
> | confusing that the `special declaration also "punches holes" in those
> | parts of the lexical overlay which were created after the last dynamic
> | binding, as in the example.
> 
>   I have no idea what this means. 

The terminology "punches holes" is from your intuitive example.  I
should say, "...including those marks on the lexical overlay which
were created after the last dynamic binding..."
 
>   I believe you still think in a different language and are unwilling to
>   let go of what you believe you understand.  Like perhaps `eval� in Perl.

No, I try to stay away from Perl :) 

I think my biggest problem is getting away from concepts picked up
from the old dynamic Lisps.

I don't think I'm having too much trouble letting go.  CL is CL.  I
only explained in detail how I was stuck because you asked.

KBK
From: Erik Naggum
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <3246683650270899@naggum.no>
* Kurt B. Kaiser
| The task of evaluating the arguments is passed to `eval�, and it proceeds
| to produce a different result than the "normal" evaluation referred to in
| the HyperSpec.

  But it does not.  That is the whole essence of this thing.

| That's the view from someone of limited CL experience.  However, I think
| I'm getting it now.

  I think what some people here fail to grasp is that `eval� is the most
  ordinary function you can think of.  Suppose you replace `eval� with
  `identity�, which returns the argument.

(let ((x 42))
  (identity x))
=> 42

(let ((x 42))
  (identity 'x))
=> x

  Now we know what `eval� /receives/.  The question is, what should it do
  with it?  By the very nature of lexical bindings, they are only visible
  in their /lexical/ scope, hence their name.  This means that when the
  function, `identity� /or/ `eval�, receives the argument, `x�, we are no
  longer in the /lexical/ scope of the binding for `x�, hence we cannot
  refer to this binding at all.

| > | On a slightly different, but closely related, subject, I find it
| > | confusing that the `special declaration also "punches holes" in those
| > | parts of the lexical overlay which were created after the last
| > | dynamic binding, as in the example.
| > 
| >   I have no idea what this means. 
| 
| The terminology "punches holes" is from your intuitive example.

  It is precisely /because/ of that that it makes no sense.  I know what I
  meant with the analogy.  What I am left with now is that it was not fully
  understood or was interpreted beyond the intended effect.

| I should say, "...including those marks on the lexical overlay which were
| created after the last dynamic binding..."

   A `special� declaration with lexical scope is different from a `special�
   proclamation, which is a declaration with global scope.

| I think my biggest problem is getting away from concepts picked up from
| the old dynamic Lisps.

  If Emacs Lisp was your first encounter with `eval�, as another poster
  suggested, realizing the effect of lexical binding could take time.

| I don't think I'm having too much trouble letting go.  CL is CL.  I only
| explained in detail how I was stuck because you asked.

  Hm.  I try to keep in mind some form of predictive intuition about what
  people I try to explain something to must have understood and where their
  points if confusion remains, but I must admit to have lost track of you.

-- 
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.
From: Kurt B. Kaiser
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <m3adk4g795.fsf@float.attbi.com>
Erik Naggum <····@naggum.no> writes:

  * KBK:
> | The task of evaluating the arguments is passed to `eval�, and it
> | proceeds to produce a different result than the "normal"
> | evaluation referred to in the HyperSpec.
> 
>   But it does not.  That is the whole essence of this thing.

OK. I understand my misconception(s) now.  And I will understand them
even better tomorrow :)

Thanks for your patience.

The examples on this thread have been very helpful and I thank everyone
for their conntributions.

[...]

>    A `special� declaration with lexical scope is different from a
>    `special� proclamation, which is a declaration with global scope.

Yes, that's the present source of my confusion.  I'm studying /
experimenting with those concepts now.

Your intuitive example involving the overlays is very clear and has
been quite useful in understanding CL environments, evaluation, and
shadowing.

[...]

>   Hm.  I try to keep in mind some form of predictive intuition about
>   what people I try to explain something to must have understood and
>   where their points if confusion remains, but I must admit to have
>   lost track of you.

We have discussed other things before, but not CL.

KBK
From: Erik Naggum
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <3246762137570341@naggum.no>
* Kurt B. Kaiser
| Your intuitive example involving the overlays is very clear and has been
| quite useful in understanding CL environments, evaluation, and shadowing.

  I am happy to hear this.

-- 
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.
From: Kenny Tilton
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <3DD9D89A.1060604@nyc.rr.com>
Kurt B. Kaiser wrote:
> However, the _effect_ of eval seems to be not quite like other
> functions because when it evaluates its argument it does so in the
> current dynamic environment, and that is definitely not what I was
> expecting.  

(defun interpret-this (some-code)
    (let ((a 1) (b 2) (c :whatever))
       (eval some-code)))

I am no expert on eval or anything else for that matter, but when I look 
at the above, I would be appalled if the evaluation of some-code were 
affected by the lexical bindings of a, b, and c.

But dynamic bindings (to my way of thinking) are inescapable, hence 
some-code "seeing" those.

Like everything else about Lisp, it works exactly as I need, want, and 
would expect it to work since the value held by the parameter some-code 
was born lexically elsewhere and seen originally by the compiler as 
literal, symbolic data only /later/ to be promoted to runnable code by 
eval.

-- 

  kenny tilton
  clinisys, inc
  ---------------------------------------------------------------
""Well, I've wrestled with reality for thirty-five years, Doctor,
   and I'm happy to state I finally won out over it.""
                                                   Elwood P. Dowd
From: Erik Naggum
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <3246676296502193@naggum.no>
* Kenny Tilton
| (defun interpret-this (some-code)
|     (let ((a 1) (b 2) (c :whatever))
|        (eval some-code)))
| 
| I am no expert on eval or anything else for that matter, but when I look
| at the above, I would be appalled if the evaluation of some-code were
| affected by the lexical bindings of a, b, and c.

  Do not forget `some-code� in this list.

  Your example is instructive for quite another reason.  Do those who think
  that `eval� should "work" in the lexical environment of the caller, also
  think this should hold for calls to `interpret-this�?  If not, why not?

-- 
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.
From: Tim Bradshaw
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <ey37kf9oqmx.fsf@cley.com>
* Erik Naggum wrote:

>   Your example is instructive for quite another reason.  Do those who think
>   that `eval� should "work" in the lexical environment of the caller, also
>   think this should hold for calls to `interpret-this�?  If not, why not?

Even more concise might be:

    (defun evalc (form)
      (funcall (compile nil `(lambda () ,form))))

I think this is an implementation of EVAL.  So the question is: if
EVAL were to `respect' (bad term) its lexical environment, how would
this be implemented?  EVALC clearly can't...

--tim
From: Paul Dietz
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <3DDAA50E.CCFFB3EE@motorola.com>
Tim Bradshaw wrote:

> Even more concise might be:
> 
>     (defun evalc (form)
>       (funcall (compile nil `(lambda () ,form))))
> 
> I think this is an implementation of EVAL.  So the question is: if
> EVAL were to `respect' (bad term) its lexical environment, how would
> this be implemented?  EVALC clearly can't...


We could modify CL to have a new special form, (CURRENT-LEXICAL-ENVIRONMENT).
The object returned by this form could be passed to EVAL as the optional
second argument, and would contain information about the lexical variables,
lexical functions and macros, go tags, block names, etc. in the current lexical
environment, as well as thunks for accessing/setting/branching to these entities.
It could also be passed to COMPILE as an optional third argument.  In both cases
the default (if the argument is missing or NIL) would be the null lexical
environment.  The function EVALC would become:

  (defun evalc (form &optional lexical-env)
     (funcall (compile nil `(lambda () ,form) lexical-env)))

I don't know if this would be *useful*, but at least it would impose no
significant extra cost if it weren't used.

	Paul
From: Tim Bradshaw
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <ey3fztxm92m.fsf@cley.com>
* Paul Dietz wrote:

> I don't know if this would be *useful*, but at least it would impose no
> significant extra cost if it weren't used.

It would, because it would require all implementations to actually
provide a current lexical environment, or to have a mode where they
could provide it.  Either compilers would have to have these two
modes, or they'd have to only have the crap mode (always have an
environment, never optimize away any variables).

That's probably not what you meant by `cost' - I'm guessing you meant
something like `clearly an implementation could be done such that this
had no runtime cost if it wasn't used (and you can always lexically
know if it's used)'.  But that's not the only kind of cost,
implementation cost also matters, I think, especially if you're an
implementor.

--tim
From: Paul F. Dietz
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <xnqdnRI3lJNvSEegXTWcpg@dls.net>
Tim Bradshaw wrote:

> That's probably not what you meant by `cost' - I'm guessing you meant
> something like `clearly an implementation could be done such that this
> had no runtime cost if it wasn't used (and you can always lexically
> know if it's used)'.  But that's not the only kind of cost,
> implementation cost also matters, I think, especially if you're an
> implementor.

Yes, that's what I meant.  Moreover, it's clear that the cost
to the implementor needn't be substantial either.  Given that the
compiler has to have a representation of the lexical environment,
building lisp code constructing the various mappings to closures
is straightforward.  This code can then be compiled normally.

	Paul
From: Tim Bradshaw
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <ey3bs4kmqa6.fsf@cley.com>
* Paul F Dietz wrote:

> Yes, that's what I meant.  Moreover, it's clear that the cost
> to the implementor needn't be substantial either.  Given that the
> compiler has to have a representation of the lexical environment,
> building lisp code constructing the various mappings to closures
> is straightforward.  This code can then be compiled normally.

I think I'd like an implementor to comment on that...
From: Frode Vatvedt Fjeld
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <2hwun876a2.fsf@vserver.cs.uit.no>
Tim Bradshaw <···@cley.com> writes:

> * Paul F Dietz wrote:
>
>> Yes, that's what I meant.  Moreover, it's clear that the cost
>> to the implementor needn't be substantial either.  Given that the
>> compiler has to have a representation of the lexical environment,
>> building lisp code constructing the various mappings to closures
>> is straightforward.  This code can then be compiled normally.
>
> I think I'd like an implementor to comment on that...

I suspect what Paul F Dietz is thinking of is that the lexical
environment could be represented by a closure like

  (lambda (var)
    (ecase var (a a) (b b) ..))

which wouldn't be of much cost to the implementor. The compiler
obviously knows the a's and b's of the lexical environment. But the
cost in terms of code efficiency would be substantial, most
likely. And would the lexical environment object have dynamic extent,
or what? I think this is a pretty useless concept.

-- 
Frode Vatvedt Fjeld
From: Paul F. Dietz
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <D8qcnUS2RrvOF0agXTWc3A@dls.net>
Frode Vatvedt Fjeld wrote:

> I suspect what Paul F Dietz is thinking of is that the lexical
> environment could be represented by a closure like
> 
>   (lambda (var)
>     (ecase var (a a) (b b) ..))
> 
> which wouldn't be of much cost to the implementor. The compiler
> obviously knows the a's and b's of the lexical environment. But the
> cost in terms of code efficiency would be substantial, most
> likely.

Something like that, yes.

If you are calling the interpreter then code efficiency isn't your
top priority anyway.  The interpreter has to be able to perform
lookups on symbols in any case.

	Paul
From: Tim Bradshaw
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <ey365usmjwe.fsf@cley.com>
* Paul F Dietz wrote:

> If you are calling the interpreter then code efficiency isn't your
> top priority anyway.  The interpreter has to be able to perform
> lookups on symbols in any case.

However, you may not be calling the interpreter.  For instance
implementations may not really have an interpreter (CMUCL doesn't, I
think, and Corman Lisp may not either).  So if you use something like:

    (defun eval (form &optional (env nil envp))
      (funcall (if envp 
                   (compile nil `(lambda () ,form) env)
                   (compile nil `(lambda () ,form)))))

Then the compiler has to be able to deal with these things too.  I
thought for a bit (ignoring anything but variable bindings) that it
could just wrap a big LET around everything to reestablish bindings,
but this won't work because they are different bindings with the same
values:

    (let ((a 1))
      (funcall (compile nil '(lambda () (setf a 2)) (current-lexical-environment)))
      a)

is 2, not 1.

I'm not trying to argue that it's not possible, but I think it might
not be that easy.

There's another question - what should be in the environment?  The
obvious things are lexical variable bindings and symbol macros, but
what about the various things that have lexical scope but dynamic
extent?  tags in TAGBODY, and block names are examples of these.  Is
it OK to say:

    (block foo
      (funcall (compile nil '(lambda () (return-from foo 1)) 
                        (current-lexical-environment))))


? I think it would be nice if it was.

--tim
From: Paul F. Dietz
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <3DDB99AC.9090802@dls.net>
Tim Bradshaw wrote:

> However, you may not be calling the interpreter.  For instance
> implementations may not really have an interpreter (CMUCL doesn't, I
> think, and Corman Lisp may not either).  So if you use something like:
> 
>     (defun eval (form &optional (env nil envp))
>       (funcall (if envp 
>                    (compile nil `(lambda () ,form) env)
>                    (compile nil `(lambda () ,form)))))
> 
> Then the compiler has to be able to deal with these things too.

When the compiler encounters a symbol that is bound in the ENV
argument, it inserts a call to appropriate thunk (either an
accessor thunk or the settor thunk).  Nothing very complicated
about that.

	Paul
From: Roger Corman
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <3dde7e7c.384521783@nntp.sonic.net>
I recently did just this in Corman Lisp. I had to create an operator
which returned the lexical environment, in a state the compiler could
use it later. The reason was to support as-needed recompilation of
CLOS methods which could access captured lexical bindings (compiled
ealier).

I found it relatively easy to wrap up the compiler state in a
structure and return that. I implemented the equivalent of
capture-lexical-environment as a special operator. If the actual
structure doesn't matter, and just needs to be in a form suitable to
feed back into the compiler, this is probably pretty easy in any
implementation. That's what I did. It would also be easy to write a
function that converts this structure to an actual environment i.e.
the type the compiler ultimately generates in the code. Note that the
returned structure includes unwind-protect records, block records, go
tags, declarations, etc.

The tricky thing, and the costly thing, is that such a brute force
exposure of the lexical variables requires that all variables be heap
bindings, rather than stack bindings. In Corman Lisp, bindings are
always stack-allocated unless they are captured by an embedded lambda.
The compiler walks the source code to determine which need to be heap
bound. I had to add a case where, if the code walker detects a call to
the capture-lexical-environment operator at any depth, it
automatically hoists all variables to heap bindings.

This has a cost, in code generation terms, of 1-2 instructions per
variable read or write, which could be a factor in a tight loop. Also,
consing is increased--functions which didn't allocate cons cells
before will now create conses. (Like so many english words, cons can
be a noun, a verb or an adjective, and I just used all three in one
sentence :-).

In general, I am skeptical of the value of making such a thing
standard, since its utility seems so system-dependent. It could really
cause problems for the optimizer if misused. I think the whole concept
of the "environment" in Common Lisp is so ill-defined as to be more a
source of confusion than utility. By environment, I mean the
environment that can be passed to macroexpand, etc. Not the concept of
the environment, which certainly makes sense as a concept.

Roger
----------------------------------------------
On 20 Nov 2002 11:30:57 +0000, Tim Bradshaw <···@cley.com> wrote:

>* Paul F Dietz wrote:
>
>> Yes, that's what I meant.  Moreover, it's clear that the cost
>> to the implementor needn't be substantial either.  Given that the
>> compiler has to have a representation of the lexical environment,
>> building lisp code constructing the various mappings to closures
>> is straightforward.  This code can then be compiled normally.
>
>I think I'd like an implementor to comment on that...
From: Pekka P. Pirinen
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <uzns42xas.fsf@globalgraphics.com>
"Paul F. Dietz" <·····@dls.net> writes:
> > > The object returned by [(CURRENT-LEXICAL-ENVIRONMENT)] could be
> > > passed to EVAL as the optional second argument, and would
> > > contain information about the lexical variables, lexical
> > > functions and macros, go tags, block names, etc. in the current
> > > lexical environment, as well as thunks for
> > > accessing/setting/branching to these entities.

"Paul F. Dietz" <·····@dls.net> writes:
> Tim Bradshaw wrote:
> > [...] implementation cost also matters, I think, especially if
> > you're an implementor.
> 
> [...] it's clear that the cost
> to the implementor needn't be substantial either.  Given that the
> compiler has to have a representation of the lexical environment,
> building lisp code constructing the various mappings to closures
> is straightforward.  This code can then be compiled normally.

So I understand you're thinking (CURRENT-LEXICAL-ENVIRONMENT) would be
transformed into something like
  (make-lexical-environment
    `((var1 . (,(lambda () var1)
               ,(lambda (new-value) (setf var1 new-value))))
      (var2 . ...)
      ...)
    `((fn1 . ...) ...)
    `((block1 . (,(lambda (val) (return-from block1 val))))
      ...)
    `((tag1 . ...) ...)
     /* declarations etc. */)

The variable and function subenvironments actually need more structure
to represent symbol macros and local macros, but macroexpansion fns
for those could be captured.  This would work.  The hairiest thing
would be to translate the variable environment back into the internal
form, when this is passed to the compiler/evaluator; the other ones
could be done by wrapping the code to be processed, say:
  (flet ((fn1 (&rest args) (apply <closure-for-fn1> args))) <code>)
but we can't do that for variables (can't use symbol macros or we lose
the distinction between them and variables - hmm, I suppose there
could be hair in MACROEXPAND and the others to hide that - anyway,
it's not straightforward).

It means there's two kinds of environments in the language, this and
the ones created by the macro mechanism.  This is confusing - or, if
we allow users to mix them, creates more complications in the
implementation.
-- 
Pekka P. Pirinen
All that glitters has a high refractive index.
From: Kent M Pitman
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <sfwk7j7yahs.fsf@shell01.TheWorld.com>
Tim Bradshaw <···@cley.com> writes:

> * Paul Dietz wrote:
> 
> > I don't know if this would be *useful*, 

Not very, I suspect.

What would you use it for?

> > but at least it would impose no
> > significant extra cost if it weren't used.

Not so, because it forces a great deal of extra work on the implementation.
 
> It would, because it would require all implementations to actually
> provide a current lexical environment, or to have a mode where they
> could provide it.

Moreover, to not do optimizations.  Consider

  (let ((x 2))
    (print (evalc 'x))
    (+ x x))

Is the compiler allowed to make the optimization

 (progn
   (print (evalc 'x))
   4)

when evalc is present in the code?  Note, too, that this means that
you cannot use evalc to 'instrument' the compiler in case of a
problem, since the compilation mode will be different depending on
whether it is present, and so it won't be telling you what you want.
From: Paul F. Dietz
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <3DDC450D.1030209@dls.net>
Kent M Pitman wrote:

>>>but at least it would impose no
>>>significant extra cost if it weren't used.
> 
> Not so, because it forces a great deal of extra work on the implementation.

I believe I have argued that it would not, in fact, impose
a great deal of extra work on the implementation.


> Moreover, to not do optimizations.  Consider
> 
>   (let ((x 2))
>     (print (evalc 'x))
>     (+ x x))
> 
> Is the compiler allowed to make the optimization
> 
>  (progn
>    (print (evalc 'x))
>    4)
> 
> when evalc is present in the code?

I proposed that EVALC take an optional argument, which is
an object returned by (CURRENT-LEXICAL-ENVIRONMENT).  So you
mean could it do the optimization when this (C-L-E) form
were present?  Clearly not, in general, but then the programmer
who uses that form is presumably a responsible individual
who would understand such things.

	Paul
From: Kent M Pitman
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <sfwk7j7k0qs.fsf@shell01.TheWorld.com>
"Paul F. Dietz" <·····@dls.net> writes:

> Kent M Pitman wrote:
> 
> >>>but at least it would impose no
> >>>significant extra cost if it weren't used.
> > Not so, because it forces a great deal of extra work on the
> > implementation.
> 
> I believe I have argued that it would not, in fact, impose
> a great deal of extra work on the implementation.
> 
> > Moreover, to not do optimizations.  Consider
> >   (let ((x 2))
> >     (print (evalc 'x))
> >     (+ x x))
> > Is the compiler allowed to make the optimization
> >  (progn
> >    (print (evalc 'x))
> >    4)
> > when evalc is present in the code?
> 
> I proposed that EVALC take an optional argument, which is
> an object returned by (CURRENT-LEXICAL-ENVIRONMENT).  So you
> mean could it do the optimization when this (C-L-E) form
> were present? 

Yes.

> Clearly not, in general, but then the programmer
> who uses that form is presumably a responsible individual
> who would understand such things.

I doubt it.  It doesn't have to do with responsibility, it has to do
with what the well-meaning programmer can and can't predict.  How
about you offer a worked sample use that is not contrived so that we
can discuss it.  It's hard to talk about this in the abstract...

As I recall, btw, Sussman wanted something like this for Scheme quite
some time back.  I don't know if MIT Scheme implemented it or what
their experience was, but you might check on it.  I remember the
concerns about optimizations, and my remarks here are mostly just
echoing my memories of what I heard then--not really new thought on my
part.
From: Paul F. Dietz
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <z4CcnWaev4OwREGgXTWcpQ@dls.net>
Kent M Pitman wrote:

> I doubt it.  It doesn't have to do with responsibility, it has to do
> with what the well-meaning programmer can and can't predict.  How
> about you offer a worked sample use that is not contrived so that we
> can discuss it.  It's hard to talk about this in the abstract...

I don't have any well-motivated example of how it could be
used.  It may very well be that this feature would not be useful
in practice.  I readily admit that without a good use it would be
silly to add such a feature.

However, I dispute your contention that the programmer could not
predict the effect of using this feature.  Indeed, *you* are predicting
the effect of this feature!

	Paul
From: Tim Bradshaw
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <ey3ptszm2tr.fsf@cley.com>
* Paul F Dietz wrote:

> However, I dispute your contention that the programmer could not
> predict the effect of using this feature.  Indeed, *you* are predicting
> the effect of this feature!

One thing it seems to me is that this trick of capturing the lexical
environment kind of defeats one purpose of lexical environments.  To
me an important aspect of them is that I can look at the code and know
what bindings/tags/block names are in effect.  Once I have a lexical
environment object I can't always do that.  When I see a call like:

    ... (compile nil `(lambda (x) (+ x y)) e) ...

I really have no idea whether this code is OK or not.  

The counter argument to this is, I guess, that these facilities would
only be meant to be used in very special cases, where people knew what
they were doing.  I guess that's true.

--tim
From: Joe Marshall
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <vg2rq9bh.fsf@ccs.neu.edu>
Kent M Pitman <······@world.std.com> writes:

> As I recall, btw, Sussman wanted something like this for Scheme quite
> some time back.  I don't know if MIT Scheme implemented it or what
> their experience was, but you might check on it.  I remember the
> concerns about optimizations, and my remarks here are mostly just
> echoing my memories of what I heard then--not really new thought on my
> part.

There is a special form (THE-ENVIRONMENT) that returns the current
lexical environment.  When MIT Scheme was all interpreted, it simply
returned the object that the interpreter was using to represent the
current environment.  Optimizations weren't a concern at that point,
but evaluating definitions were.  Given some environment you could
eval (DEFINE FOO ...) in that environment.  This would shadow any
lexically visible definitions of FOO that may have been visible from
an outer environment.  However, this breaks `lexical addressing'
(whereby you can determine the frame and offset of a lexical variable
statically rather than having to do a `deep search').  The MIT Scheme
interpreter would cache the lexical address of a variable upon
evaluation.  When you called eval and installed a new binding using
DEFINE, it would have to invalidate the cache.  It was very hairy
code.

In order to support compiled code (that is, compiled code that didn't
just inline the interpreter), they needed to change the model.  If a
binding could be introduced after the fact anywhere in the code, no
optimizations were possible.  So now MIT Scheme distinguishes between
environments created by lambda bindings and those created as
`top-level' environments.  Top-level environments are a mapping from
variable name to value cells, but lambda-bound environments are
usually just a vector of value cells.  (THE-ENVIRONMENT) can now only
be called in a top-level environment.
From: William D Clinger
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <b84e9a9f.0211211115.290c9ea@posting.google.com>
Concerning (CURRENT-LEXICAL-ENVIRONMENT), Kent M Pitman wrote:
> As I recall, btw, Sussman wanted something like this for Scheme quite
> some time back.  I don't know if MIT Scheme implemented it or what
> their experience was, but you might check on it.  I remember the
> concerns about optimizations, and my remarks here are mostly just
> echoing my memories of what I heard then--not really new thought on my
> part.

Yes, MIT Scheme implemented (CURRENT-LEXICAL-ENVIRONMENT), but with
a different name that I don't remember offhand.  I believe this form
was actually used in the first edition of "Structure and Interpretation
of Computer Programs", but I assume it does not appear in the second
edition.

As for optimization, the usual approach is to disable all relevant
optimizations for expressions that contain a use of
(CURRENT-LEXICAL-ENVIRONMENT).  This isn't hard to implement, and
it wouldn't necessarily have much effect on performance because
well-informed programmers would know not to use this feature in
performance-critical code, but (CURRENT-LEXICAL-ENVIRONMENT) would
have to be part of the core language, and it's hard to argue that
(CURRENT-LEXICAL-ENVIRONMENT) is worth increasing the size of core
Scheme by 15%.  It might be easier to make this argument for CL.

Will
From: Kent M Pitman
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <sfwbs4ixtj5.fsf@shell01.TheWorld.com>
"Paul F. Dietz" <·····@dls.net> writes:

> Kent M Pitman wrote:
> 
> > I doubt it.  It doesn't have to do with responsibility, it has to do
> > with what the well-meaning programmer can and can't predict.  How
> > about you offer a worked sample use that is not contrived so that we
> > can discuss it.  It's hard to talk about this in the abstract...
> 
> I don't have any well-motivated example of how it could be
> used.  It may very well be that this feature would not be useful
> in practice.  I readily admit that without a good use it would be
> silly to add such a feature.
> 
> However, I dispute your contention that the programmer could not
> predict the effect of using this feature.  Indeed, *you* are predicting
> the effect of this feature!

Well, I am saying that in the 20 years since this idea was proposed, I
have not heard a single good use proposed and I've seen a number of
ill consequences discussed.  I've never seen anyone held back by the
absence of the feature.

This kind of "prediction" (if that's what I'm doing) is not symmetric with
the kind of predicting I'm talking about.  I believe I have some good reasons
to expect the user can get into trouble, but it would be easier for me to
give you examples if I had at least a worked example of a case you thought
someone could be responsible.  If you can't even come up with a plausible
example to be refuted, what difference does it make whether I can or cannot
do the kind of predicting you're accusing me of?

So I don't find myself swayed by your disputing me, but of course I'm
not a final authority on much of anything. ;)
From: Kent M Pitman
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <sfw65uqxteu.fsf@shell01.TheWorld.com>
Joe Marshall <···@ccs.neu.edu> writes:

> Kent M Pitman <······@world.std.com> writes:
... 
> In order to support compiled code (that is, compiled code that didn't
> just inline the interpreter), they needed to change the model.  If a
> binding could be introduced after the fact anywhere in the code, no
> optimizations were possible.  So now MIT Scheme distinguishes between
> environments created by lambda bindings and those created as
> `top-level' environments.  Top-level environments are a mapping from
> variable name to value cells, but lambda-bound environments are
> usually just a vector of value cells.  (THE-ENVIRONMENT) can now only
> be called in a top-level environment.

This is very similar to the T "locale" notion.
From: Tim Bradshaw
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <ey3bs4lor7e.fsf@cley.com>
* Kurt B Kaiser wrote:
> I would have expected eval to evaluate its argument in the lexical
> environment of the let block.  Other functions, like print, have their
> arguments evaluated in that lexical environment before being passed.

yes, and the argument *is* evaluated in the current lexical & dynamic
environments - EVAL is *just an ordinary function*.  However, once the
argument has been evaluated, and passed to EVAL, it is evaluated
*again* - because that is what EVAL does, and this *second* evaluation
is in the null lexical and current dynamic environments, because there
is no mechanism for it to be otherwise, since EVAL is an ordinary
function.

--tim
From: Coby Beck
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <arcmep$1kh9$1@otis.netspace.net.au>
"Kurt B. Kaiser" <···@shore.net> wrote in message
···················@float.attbi.com...

> * (let ((x 20))
>     (declare (special x))
>     (let ((x 30))
>       (print x)
>       (eval 'x)))
> 30
> 20
> *
> ----------
>
> I would have expected eval to evaluate its argument in the lexical
> environment of the let block.  Other functions, like print, have their
> arguments evaluated in that lexical environment before being passed.

eval is the same, consider this:
(let ((x 20))
  (declare (special x))
  (let ((x 30))
    (print 'x)
    (print x)
    (values
     (eval 'x)
     (eval x))))

X
30
20
30


--
Coby Beck
(remove #\Space "coby 101 @ bigpond . com")
From: Lars Magne Ingebrigtsen
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <m3bs4mkqys.fsf@quimbies.gnus.org>
Erik Naggum <····@naggum.no> writes:

> I am genuinely puzzled: Why is this so hard to grasp?

I certainly was surprised the first time I used `eval' in Common Lisp.
I was used to `eval'-ing things in Emacs Lisp, and Emacs Lisp doesn't
have lexical bindings.  I didn't consider the implications on lexical
bindings on `eval'.

-- 
(domestic pets only, the antidote for overdose, milk.)
   ·····@gnus.org * Lars Magne Ingebrigtsen
From: Aleksandr Skobelev
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <m3lm3rezl4.fsf@list.ru>
Nils Goesche <···@cartan.de> writes:

> Aleksandr Skobelev <···········@list.ru> writes:

> >     "The null lexical environment is equivalent to the global
> >      environment."
> > 
> > What the equivalence do they speak about?
> 
> As I understand it, it means that whenever it says that a form is
> evaluated in the null lexical environment, like the argument to
> EVAL, for instance, it cannot access any lexically apparent
> bindings.  The only bindings it /can/ access are those in the
> global environment and the current dynamic environment, but /no/
> lexical ones.

Yes, but there is nothing about the current dynamic environment in that
statement. So, it looks like we give some free interpretation for it.

> 
> > Do they mean that, like the global environment, the null
> > lexical environment contains no lexical bindings?
> 
> Yes.  I was only wondering about if it would make sense to
> /introduce/ a notion of a global lexical binding when speaking
> about Common Lisp to make it easier to explain some freaky code
> snippets of questionable legal status. 

Hmm, I'm not sure about how such a notion could be useful. It might be
that some examples of such freaky code (if you can find some easily) 
could clear it.

> > I'm confused. :(
> 
> I hope it wasn't me who caused that :-)

I'm afraid, I do it myself. :)
From: Nils Goesche
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <lkd6p3uf0h.fsf@cartan.de>
Aleksandr Skobelev <···········@list.ru> writes:

> Nils Goesche <···@cartan.de> writes:
> 
> > Aleksandr Skobelev <···········@list.ru> writes:
> 
> > >     "The null lexical environment is equivalent to the global
> > >      environment."
> > > 
> > > What the equivalence do they speak about?
> > 
> > As I understand it, it means that whenever it says that a form is
> > evaluated in the null lexical environment, like the argument to
> > EVAL, for instance, it cannot access any lexically apparent
> > bindings.  The only bindings it /can/ access are those in the
> > global environment and the current dynamic environment, but /no/
> > lexical ones.
> 
> Yes, but there is nothing about the current dynamic environment in
> that statement. So, it looks like we give some free interpretation
> for it.

I added ``the current dynamic environment�� because EVALed forms can
access it (see dictionary entry for EVAL) /and/ the null lexical
environment:

CL-USER 133 > (defvar *foo* 42)
*FOO*

CL-USER 134 > *foo*
42

CL-USER 135 > (let ((*foo* 40))
                (eval '(+ *foo* 2)))
42

works as well (*FOO* coming from the current dynamic environment) as

CL-USER 136 > (eval '(logand #xFF most-positive-fixnum))
255

(MOST-POSITIVE-FIXNUM available in the null lexical environment,
because it is part of the global environment).

> > > Do they mean that, like the global environment, the null
> > > lexical environment contains no lexical bindings?
> > 
> > Yes.  I was only wondering about if it would make sense to
> > /introduce/ a notion of a global lexical binding when speaking
> > about Common Lisp to make it easier to explain some freaky code
> > snippets of questionable legal status. 
> 
> Hmm, I'm not sure about how such a notion could be useful. It might
> be that some examples of such freaky code (if you can find some
> easily) could clear it.

I doubt it, but I posted some earlier in this thread.

Regards,
-- 
Nils G�sche
"Don't ask for whom the <CTRL-G> tolls."

PGP key ID 0x0655CFA0
From: Erik Naggum
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <3246569973032676@naggum.no>
* Aleksandr Skobelev
| What the equivalence do they speak about?

  Sigh.  It means that when somebody says the "null lexical environment",
  the expressin contains relevant information about (at least) two things:
  (1) the perspective and (2) the object.  The same holds for "the global
  environment", of course, in which case the object is the same as for the
  previous expression, but the /perspective/ is not.

| Do they mean that, like the global environment, the null lexical
| environment contains no lexical bindings?

  The global environment is what you get when you have no lexical bindings.

  The point here is that the lexical environment shadows the global.  When
  you have an empty/null lexical environment, you have nothing that could
  shadow the global environment, therefore the consequence of viewing your
  environment through the now empty/transparent lexical environment is that
  you see only the background global environment.  But it is possible to
  look at the global environment /without/ looking through a transparent
  lexical environment that shadows nothing, hence the two perspectives have
  different names.

  Think of bindings as squares on a blackboard.  You can flip overlays over
  the blackboard from both sides, and the overlays can have opaque squares
  that shadow any other bindings but otherwise be transparent.  Now, the
  overlays attached to one side holds overlays for special bindings while
  the other side holds lexical overlays, so you can flip them in from both
  sides.  A `special� proclamation means that you cut a whole in all the
  lexical overlays so that you will always see the dynamic bindings.  When
  you make a special binding, you make an opaque square on an overlay you
  have flipped in from the special side and scribble on it.  When you make a
  lexical binding, you make an opaque square on an overlay you have flipped
  in from the lexical side and scribble on it.  When you call a function,
  you temporarily remove all your lexical overlays, but the special overlays
  remain, and you use a fresh set of lexical overlays.  Now, if you make no
  lexical bindings on this fresh set of overlays, you have the null lexical
  environment.  This is what `eval� starts out with, just like any other
  function before it makes its own lexical bindings, such as for incoming
  arguments (which may also cause special bindings, btw).

  Did that make the issue opaque or transparent?

  And, please, there is no global lexical environment.  While some evidently
  think it is descriptive of something, it is an oxymoron that only confuses
  people who do not understand what is going on.

-- 
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.
From: Aleksandr Skobelev
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <m3ptt3f0tp.fsf@list.ru>
Erik Naggum <····@naggum.no> writes:

> * Aleksandr Skobelev
> | What the equivalence do they speak about?
> 
>   Sigh.  It means that when somebody says the "null lexical environment",
>   the expressin contains relevant information about (at least) two things:
>   (1) the perspective and (2) the object.  The same holds for "the global
>   environment", of course, in which case the object is the same as for the
>   previous expression, but the /perspective/ is not.
> 
> | Do they mean that, like the global environment, the null lexical
> | environment contains no lexical bindings?
> 
>   The global environment is what you get when you have no lexical bindings.
> 
>   The point here is that the lexical environment shadows the global.  When
>   you have an empty/null lexical environment, you have nothing that could
>   shadow the global environment, therefore the consequence of viewing your
>   environment through the now empty/transparent lexical environment is that
>   you see only the background global environment.  But it is possible to
>   look at the global environment /without/ looking through a transparent
>   lexical environment that shadows nothing, hence the two perspectives have
>   different names.

Hmm. It might be there is a mess in my poor head, but how about dynamic
environments? 

----------
* (setf x 10)
Warning: This variable is undefined:
  X

10
* (let ((x 20))
    (declare (special x)) 
    (let ((x 30)) 
      (print x)
      (eval 'x)))
30 
20
* 
----------

Here the lexical binding to 30 shadows the dynamic binding to 20, which
is in dynamic, but not the global environment. But eval sees 20, not 10.
So, isn't null lexical environment equivalent to a some dynamic + the
global environment?

> 
>   Think of bindings as squares on a blackboard.  You can flip overlays over
>   the blackboard from both sides, and the overlays can have opaque squares
>   that shadow any other bindings but otherwise be transparent.  Now, the
>   overlays attached to one side holds overlays for special bindings while
>   the other side holds lexical overlays, so you can flip them in from both
>   sides.  A `special� proclamation means that you cut a whole in all the
>   lexical overlays so that you will always see the dynamic bindings.  When
>   you make a special binding, you make an opaque square on an overlay you
>   have flipped in from the special side and scribble on it.  When you make a
>   lexical binding, you make an opaque square on an overlay you have flipped
>   in from the lexical side and scribble on it.  When you call a function,
>   you temporarily remove all your lexical overlays, but the special overlays
>   remain, and you use a fresh set of lexical overlays.  Now, if you make no
>   lexical bindings on this fresh set of overlays, you have the null lexical
>   environment.  This is what `eval� starts out with, just like any other
>   function before it makes its own lexical bindings, such as for incoming
>   arguments (which may also cause special bindings, btw).
> 
>   Did that make the issue opaque or transparent?

Sorry, I'm afraid I became enmeshed who has been overlaid by whom here. :)

Thank you. I think (well, I hope) I understand how fresh lexical/dynamic
bindings shadow each other and bindings in the global environment. What I
don't understand clear (and what I wrote about in my previous message) is
the usage of 'equivalent' word in the standard. Does it have the strict
technical or just some free, descriptive meaning? Just now it looks for
me like it is just descriptive and not absolutly full (if remember about
bindings in dynamic environments). But I suspect, that it might be
something wrong in my reasoning. :(
 

> 
>   And, please, there is no global lexical environment.  While some evidently
>   think it is descriptive of something, it is an oxymoron that only confuses
>   people who do not understand what is going on.

Hear!

> 
> -- 
> 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.
From: Nils Goesche
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <lk8yzruekd.fsf@cartan.de>
Aleksandr Skobelev <···········@list.ru> writes:

> ----------
> * (setf x 10)
> Warning: This variable is undefined:
>   X
> 
> 10
> * (let ((x 20))
>     (declare (special x)) 
>     (let ((x 30)) 
>       (print x)
>       (eval 'x)))
> 30 
> 20
> * 
> ----------

Nice example, actually.  Although you should somehow globally declare
X special, maybe by using DEFPARAMETER instead of just SETF, to clear
all doubt.

> Here the lexical binding to 30 shadows the dynamic binding to 20,
> which is in dynamic, but not the global environment. But eval sees
> 20, not 10.  So, isn't null lexical environment equivalent to a some
> dynamic + the global environment?

No.  EVAL can access /both/ a null lexical environment (meaning the
lexically apparent binding of x to 30 isn't visible) /and/ the current
dynamic environment.  This is a specialty of EVAL (see its dictionary
entry) but has nothing to do with the term ``null lexical
environment�� in itself.

Regards,
-- 
Nils G�sche
"Don't ask for whom the <CTRL-G> tolls."

PGP key ID 0x0655CFA0
From: Nils Goesche
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <lk4raevs95.fsf@cartan.de>
I <······@cartan.de> wrote:

> Aleksandr Skobelev <···········@list.ru> writes:
> 
> > Here the lexical binding to 30 shadows the dynamic binding to 20,
> > which is in dynamic, but not the global environment. But eval sees
> > 20, not 10.  So, isn't null lexical environment equivalent to a some
> > dynamic + the global environment?
> 
> No.  EVAL can access /both/ a null lexical environment (meaning the
> lexically apparent binding of x to 30 isn't visible) /and/ the current
> dynamic environment.

Aargh, this sounds dumb.  We say ``null lexical environment�� only to
emphasize that no lexically apparent binding is visible.  That implies
that evaluating a form in a null lexical environment is ``equivalent��
to evaluating it in the global environment -- but the bindings of
dynamic variables are /part/ of the global environment!  So it isn't
really necessary to say ``some dynamic + the global environment��
because the latter contains the former, anyway.  But understanding
your example is made easier if one emphasizes that the current dynamic
environment is indeed visible.

Sorry,
-- 
Nils G�sche
"Don't ask for whom the <CTRL-G> tolls."

PGP key ID 0x0655CFA0
From: Aleksandr Skobelev
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <m33cpy679i.fsf@list.ru>
Nils Goesche <······@cartan.de> writes:

> I <······@cartan.de> wrote:
> 
> > No.  EVAL can access /both/ a null lexical environment (meaning the
> > lexically apparent binding of x to 30 isn't visible) /and/ the current
> > dynamic environment.
> 
> Aargh, this sounds dumb.  We say ``null lexical environment�� only to
> emphasize that no lexically apparent binding is visible.  That implies
> that evaluating a form in a null lexical environment is ``equivalent��
> to evaluating it in the global environment -- but the bindings of
> dynamic variables are /part/ of the global environment! 

I'm not sure. For the global environment contains bindings with 
indefinite scope and indefinite extent, while dynamic binding in LET form
has dynamic extent (limited inside the form).

> So it isn't
> really necessary to say ``some dynamic + the global environment��
> because the latter contains the former, anyway.

I inclined to consider them as different notions. The global environment
is an object of environment class that "contains, among other things, the
following:

  * bindings of dynamic variables and constant variables.
  * bindings of functions, macros, and special operators.
  * bindings of compiler macros.
  * bindings of type and class names
  * information about proclamations."

There is only one such object. 

A dynamic environment is a class of environment that "contains, among
other things, the following:

  * bindings for dynamic variables.
  * information about active catch tags.
  * information about exit points established by unwind-protect.
  * information about active handlers and restarts."

So I see that each class contains information that is not in other. And
because of that I don't able to say that one class include other.

If consider model where several Lisp processes run there are only one 
global environment and several dynamic environments simultaneously 
(one per process).

That are my reasonings. But they of course might have some, still
undisclosed for me, deficiencies.
From: Nils Goesche
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <lkisyuu1nm.fsf@cartan.de>
Aleksandr Skobelev <···········@list.ru> writes:

> Nils Goesche <······@cartan.de> writes:

> > We say ``null lexical environment�� only to emphasize that no
> > lexically apparent binding is visible.  That implies that
> > evaluating a form in a null lexical environment is ``equivalent��
> > to evaluating it in the global environment -- but the bindings of
> > dynamic variables are /part/ of the global environment!
> 
> I'm not sure. For the global environment contains bindings with
> indefinite scope and indefinite extent, while dynamic binding in LET
> form has dynamic extent (limited inside the form).

I don't think it makes much of a difference whether you define it one
way or the other.  For instance, we have

# 3.1.2.1.1.2 Dynamic Variables

# At any given time, all dynamic variables with a given name refer to
# exactly one binding, either in the dynamic environment or in the
# global environment.

> > So it isn't really necessary to say ``some dynamic + the global
> > environment�� because the latter contains the former, anyway.

Ok, this seems to be imprecise (or even wrong).

> I inclined to consider them as different notions. The global
> environment is an object of environment class that "contains, among
> other things, the following:

[snip]

> So I see that each class contains information that is not in
> other. And because of that I don't able to say that one class
> include other.

Ok.

> That are my reasonings. But they of course might have some, still
> undisclosed for me, deficiencies.

Sounds good to me.

Regards,
-- 
Nils G�sche
"Don't ask for whom the <CTRL-G> tolls."

PGP key ID 0x0655CFA0
From: Kurt B. Kaiser
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <m33cpyibtx.fsf@float.attbi.com>
Nils Goesche <······@cartan.de> writes:

> > > So it isn't really necessary to say ``some dynamic + the global
> > > environment�� because the latter contains the former, anyway.
> 
> Ok, this seems to be imprecise (or even wrong).

In threaded code, I take it that each thread has its own dynamic
environment, but shares the global environment.

KBK
From: Erik Naggum
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <3246668644674564@naggum.no>
* Kurt B. Kaiser
| In threaded code, I take it that each thread has its own dynamic
| environment, but shares the global environment.

  Good observation.  This is normally the case.

-- 
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.
From: Aleksandr Skobelev
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <m37kfa6aju.fsf@list.ru>
Nils Goesche <······@cartan.de> writes:

> Aleksandr Skobelev <···········@list.ru> writes:
> 
> > ----------
> > * (setf x 10)
> > Warning: This variable is undefined:
> >   X
> > 
> > 10
> > * (let ((x 20))
> >     (declare (special x)) 
> >     (let ((x 30)) 
> >       (print x)
> >       (eval 'x)))
> > 30 
> > 20
> > * 
> > ----------
> 
> Nice example, actually.  Although you should somehow globally declare
> X special, maybe by using DEFPARAMETER instead of just SETF, to clear
> all doubt.

Thanks. :) But it'd be an error to claim X special globally, because it'd
make all bindings for X dynamic. Whereas we need both dynamic and lexical
bindings here. (This example was produced under CMUCL with 
'(setf *top-level-auto-declare* nil)' that switched off autodeclaration
of free global variables to be special.)
From: Nils Goesche
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <lkn0o6u25z.fsf@cartan.de>
Aleksandr Skobelev <···········@list.ru> writes:

> Nils Goesche <······@cartan.de> writes:
> 
> > Aleksandr Skobelev <···········@list.ru> writes:
> > 
> > > ----------
> > > * (setf x 10)
> > > Warning: This variable is undefined:
> > >   X
> > > 
> > > 10
> > > * (let ((x 20))
> > >     (declare (special x)) 
> > >     (let ((x 30)) 
> > >       (print x)
> > >       (eval 'x)))
> > > 30 
> > > 20
> > > * 
> > > ----------
> > 
> > Nice example, actually.  Although you should somehow globally
> > declare X special, maybe by using DEFPARAMETER instead of just
> > SETF, to clear all doubt.
> 
> Thanks. :) But it'd be an error to claim X special globally, because
> it'd make all bindings for X dynamic. Whereas we need both dynamic
> and lexical bindings here.

Duh!  Correct, sorry.  I guess I am too tired today.  I'll go home and
have some sleep now.

Regards,
-- 
Nils G�sche
"Don't ask for whom the <CTRL-G> tolls."

PGP key ID 0x0655CFA0
From: Erik Naggum
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <3246632088492607@naggum.no>
* Aleksandr Skobelev <···········@list.ru>
| So, isn't null lexical environment equivalent to a some dynamic + the
| global environment?

  No.

-- 
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.
From: Kurt B. Kaiser
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <m3k7jaiq9f.fsf@float.attbi.com>
Erik Naggum <····@naggum.no> writes:

>   Did that make the issue opaque or transparent?

Very nice.  When do you write your introductory Lisp text?

Followed, hopefully, by the Lisp 101 text.

KBK
From: Nils Goesche
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <8765ux7344.fsf@darkstar.cartan>
I <···@cartan.de> wrote:

> While this sounds a bit like an oxymoron because lexical
> bindings are usually lexically restricted to establishing forms
> and have dynamic extent, [...]

Oops, scratch that dynamic extent thing.

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

PGP key ID #xD26EF2A0
From: Joe Marshall
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <lm3qpxsn.fsf@ccs.neu.edu>
Nils Goesche <···@cartan.de> writes:

> Sure.  What I am trying to understand is the following:
> 
> CL-USER 30 > (eval 'most-positive-double-float)
> 1.7976931348623165E308
> 
> CL-USER 31 > (setf (symbol-value 'x) 42)
> 42
> 
> CL-USER 32 > (eval 'x)
> 42
> 
> There is indeed no lexically apparent binding for those two
> symbols.  But their values are looked up somewhere, in an
> environment.  Which is it?

Let me be pedantic here.  The examples you are giving are fragments of
lisp code.  Within these fragments are `identifiers' (symbolic tokens
with names such as "let", "x", and "declare") and `literals' (things
like 17).  Some of the identifiers refer to `variables', some refer to
special syntactic forms.  An identifier may refer to a `bound'
variable, or it may be a `free' variable.  There are two rules for
evaluating a bound variable:  If the variable is not `special', use
the binding in the closest lexical context.  If the variable *is*
`special', look in the `value cell' of the symbol with the same name
as the variable.

There is a special evaluation rule for free variables:  always look in
the `value cell' of the symbol with the same name as the variable.

> Neither MOST-POSITIVE-DOUBLE-FLOAT nor X have been declaimed
> special, however.

So in these cases:

> CL-USER 30 > (eval 'most-positive-double-float)
> 1.7976931348623165E308

> CL-USER 32 > (eval 'x)
> 42

the variables `most-positive-double-float' and `x' are free variables,
so the rule for free variables applies and the value cell is used.
(The rule for lexical variables does *not* apply because there is no
lexical binding.) 

> The global environment, obviously, which is also called ``null
> lexical environment�� to emphasize that it contains no lexically
> apparent bindings (see 3.1.1.3.1 The Null Lexical Environment).
> 
> Now, MOST-POSITIVE-DOUBLE-FLOAT is a constant, which is not so
> interesting, but X is not.  I can do
> 
> CL-USER 33 > (setf (symbol-value 'x) 17)
> 17
> 
> CL-USER 34 > (eval 'x)
> 17
>
> anytime I want.  I can also do

This uses the free variable rule.


> CL-USER 35 > (let ((x 13))
>                (+ x 5))
> 18

This uses the lexical variable rule.

> I would also like to try the following:
> 
> (defun test (y)
>   (+ x y))

Note that in the function TEST, the variable `x' is free, so the free
variable rule is used:  the value cell of the symbol X will be used.

> (let ((x 20))
>   (test 7))

But in this fragment, `x' is lexically bound.  There is no way that
the function TEST (or any other function) can refer to this binding.

> Now, 3.2.2.3 Semantic Constraints says:
> 
> # Special proclamations for dynamic variables must be made in the
> # compilation environment.  Any binding for which there is no
> # special declaration or proclamation in the compilation
> # environment is treated by the compiler as a lexical binding.

In other words, if `x' is not special, then (let ((x 22)) ...)
establishes a lexical binding for `x', not a special binding.

> But I might snottily claim that I don't want X to be special,
> anyway :-)
> 
> But what the heck, let's do it anyway:
> 
> CL-USER 36 > (defun test (y)
>                (+ x y))
> Warning: Syntactic warning for form X:
>    X assumed special.
> TEST
> 
> CL-USER 37 > (let ((x 20))
>                (test 7))
> 24
> 
> as expected.  
> 
> Whether this is legal code or not is not so interesting at the
> moment; what I like is that we can explain everything that
> happened in the above experiments without resorting to
> implementation issues if we simply say that X is part of such a
> thing as a ``global lexical environment��. 

Well, I suppose you can call the collection of all value cells the
`global lexical environment', but I wouldn't.

> While this sounds a bit like an oxymoron because lexical bindings
> are usually lexically restricted to establishing forms and have
> dynamic extent, it is well possible to give the term a reasonable
> meaning.

Lexical variables have indefinite extent (you might close over them).


> Now, what happens if we do
> 
> CL-USER 38 > (declaim (special x))
> NIL
> 
> CL-USER 39 > (let ((x 20))
>                (test 7))
> 27
> 
> By globally declaring X special, we instruct the system to
> perform the last binding in the dynamic environment, instead.  It
> is rather puzzling that TEST already behaves accordingly, too!

It shouldn't be puzzling.  When you declaim X to be special, you
explicitly tell the compiler that when X is bound (as in the LET
statement that follows) the value cell of the symbol X should hold the
binding.

> So, now X is also part of the (global) dynamic environment,
> obviously.  And it has kept its value :-)

I wouldn't say it quite that way.  By declaiming X to be special, you
have changed the binding discipline for that variable.  It keeps its
value in either case, it is just a matter of where that value is
stored (and of course the dynamic extent of the binding).
From: Nils Goesche
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <lkr8diu478.fsf@cartan.de>
Joe Marshall <···@ccs.neu.edu> writes:

> Nils Goesche <···@cartan.de> writes:
> 
> > Sure.  What I am trying to understand is the following:
> > 
> > CL-USER 30 > (eval 'most-positive-double-float)
> > 1.7976931348623165E308
> > 
> > CL-USER 31 > (setf (symbol-value 'x) 42)
> > 42
> > 
> > CL-USER 32 > (eval 'x)
> > 42
> > 
> > There is indeed no lexically apparent binding for those two
> > symbols.  But their values are looked up somewhere, in an
> > environment.  Which is it?

[snip]

> There is a special evaluation rule for free variables: always look
> in the `value cell' of the symbol with the same name as the
> variable.

Yes, that this is what's actually done has been clear all the time.  I
had been trying to explain all those evaluations /without/ referring
to this technique, I called that ``referring to the implementation��,
rather than pure semantics.  But maybe that was my mistake: This
lookup technique is actually part of the abstract semantics of the
language (at least if all the snippets are legal).  The ease with
which you can explain everything now is certainly compelling,
especially when compared to my clumsy attempts of doing everything
with types of environments that don't even exist in the first place :-)

> > While this sounds a bit like an oxymoron because lexical bindings
> > are usually lexically restricted to establishing forms and have
> > dynamic extent, it is well possible to give the term a reasonable
> > meaning.
> 
> Lexical variables have indefinite extent (you might close over
> them).

Yes, sorry again about this typo/thinko.

> > So, now X is also part of the (global) dynamic environment,
> > obviously.  And it has kept its value :-)
> 
> I wouldn't say it quite that way.  By declaiming X to be special,
> you have changed the binding discipline for that variable.  It keeps
> its value in either case, it is just a matter of where that value is
> stored (and of course the dynamic extent of the binding).

Sounds much better, indeed.  Thanks for your patience.

Regards,
-- 
Nils G�sche
"Don't ask for whom the <CTRL-G> tolls."

PGP key ID 0x0655CFA0
From: Harald Hanche-Olsen
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <pcok7jll1ad.fsf@thoth.math.ntnu.no>
+ ···@jpl.nasa.gov (Erann Gat):

| 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).

| Please send comments by email if possible to ···@jpl.nasa.gov.

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?
From: thelifter
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <b295356a.0211141637.395d5010@posting.google.com>
···@jpl.nasa.gov (Erann Gat) wrote in message news:<····················@192.168.1.51>...

> 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.

> 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.

> 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.

> 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!
From: Erann Gat
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <gat-1411021740440001@k-137-79-50-101.jpl.nasa.gov>
In article <····························@posting.google.com>,
·········@gmx.net (thelifter) wrote:

> 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.

> 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.
From: thelifter
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <b295356a.0211150000.2f571802@posting.google.com>
···@jpl.nasa.gov (Erann Gat) wrote in message news:<····················@k-137-79-50-101.jpl.nasa.gov>...

> > 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.

That's one of the things I don't understand, can you explain me the
difference please or give a good pointer(Sorry, I'm just an idiot)?

You also said that names are mostly symbols but sometimes can be
strings also. Can you make clear which cases you mean? If I understood
you correctly the only case where a name is a string is when you are
referring to the name of the symbol correct?

Best regards...theIdiot

PS: I'm ignoring Erik Naggums comments. They are negative as always, I
spare my time to answer the constructive posts.
From: Erann Gat
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <gat-1511020948210001@192.168.1.51>
In article <····························@posting.google.com>,
·········@gmx.net (thelifter) wrote:

> ···@jpl.nasa.gov (Erann Gat) wrote in message
news:<····················@k-137-79-50-101.jpl.nasa.gov>...
> 
> > > 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.
> 
> That's one of the things I don't understand, can you explain me the
> difference please or give a good pointer(Sorry, I'm just an idiot)?

Well, I thought I'd given it a pretty good shot in the "idiot's guide" but
I guess not.

Do you understand that there is a difference between a thing and its
name?  For example, there is a difference between "Erik" (which is a
string of characters) and Erik (which is a person).  The name "Erik"
refers to the person Erik, but the name and the person are not the same
thing.

The problem is that the only tool we have for talking about these things
are names.  Its hard to talk about Erik without using his name.

Likewise, it's hard to talk about a variable named "X" without using its name.

In the case of C programs we can distinguish between variables and their
names in the same way we distinguish between people and their names, by
putting the names in double quotes.  So in C there is a difference between
"X" (which is a name) and X (which is a variable).  With me so far?

In Common Lisp we can't do that because there are *three* concepts that we
have to distinguish between, not just two, because in Common Lisp, unlike
C, the names of variables are first-class data items (called symbols).  A
symbol is just an object pretty much like any other, except that 1)
symbols have names and 2) there is a convenient typographical convention
for distinguishing between a symbol and its name.  We write FOO (without
quotes) to mean 'the symbol named "FOO"' just like we write Erik (without
quotes) to mean 'the person named "Erik"'.

The problem is we've now run out of typographical conventions.  We've got
the string "FOO" and the symbol FOO, but no notation left to talk about
the variable whose name is (the symbol) FOO, except to write out that very
phrase ("the variable whose name is FOO").  So we have to invent a new
notation out of whole cloth.  The notation I invented for the guide was
FOO*n, where n is a number.

I could have used a different convention, and used a single-quote to
denote symbols.  So I could have talked about the string "FOO" being the
name of the symbol 'FOO which is the name of the variable FOO.  The
problem with that is that there can be more than one variable named FOO
(just like there can be more than one person named Erik), and so I
invented the *n notation to distinguish between multiple variables with
the same name.

Did that help?

E.
From: Lieven Marchand
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <87n0obht40.fsf@wyrd.be>
·········@gmx.net (thelifter) writes:

> PS: I'm ignoring Erik Naggums comments. They are negative as always, I
> spare my time to answer the constructive posts.

And that's of course a very positive and constructive aside. If you
want to ignore Erik, that's your right and prerogative, but don't make
a public production out of it.

-- 
When they ran out of ships, they used guns. When they ran out of guns,
they used knives and sticks and bare hands. They did this for two
years. They never ran out of courage. But in the end, they ran out of
time.                                          B5 --- In the Beginning
From: Erik Naggum
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <3246379214153439@naggum.no>
* ·········@gmx.net (thelifter)
| PS: I'm ignoring Erik Naggums comments. They are negative as always, I
| spare my time to answer the constructive posts.

  Ever wondered /why/ they are negative towards people like you?  Sheesh.

  But that you have to mention it is actually quite amusing.

-- 
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.
From: Alain Picard
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <87r8dnoxy2.fsf@optushome.com.au>
·········@gmx.net (thelifter) writes:

> ···@jpl.nasa.gov (Erann Gat) wrote in message news:<····················@k-137-79-50-101.jpl.nasa.gov>...
> 
> > But they aren't.  Variables and symbols are two different things.
> 
> That's one of the things I don't understand, can you explain me the
> difference please or give a good pointer(Sorry, I'm just an idiot)?

Ok, try this.  Forget the word "variable" for a moment.  There ARE no
"variables".  There are only symbols and values.  When you evaluate an
expression, and that expression happens to be a symbol, you need to
fetch the value currently _bound_ to that symbol.  Values are bound to
symbols using, funnily enough, binding establishing forms [the most
common of which is LET].

Bindings are looked up either lexically or dynamically, depending on
whether the symbol being looked up is known to be _special_ in the
context for which the evaluation is proceeding.

Now, does that help, or merely confuse even more?
From: thelifter
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <b295356a.0211150925.1c4aefae@posting.google.com>
Alain Picard <·······················@optushome.com.au> wrote in message news:<··············@optushome.com.au>...
> Ok, try this.  Forget the word "variable" for a moment.  There ARE no
> "variables".  There are only symbols and values.  When you evaluate an

I just took a look at the language specification. It seems that the
main problem is, that there is no definition for variable:

<quote>
5.1.2. Variables

Symbols are used as names of variables in Common Lisp programs.
</quote>

This is in accordance with what Eran Gatt wrote. So what is a variable
now?
Can someone provide the answer for me? Maybe we should start a new
thread on it?

There are always problems if we use things that we haven't defined.

Best regards,

theIdiot
From: Erann Gat
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <gat-1511021021590001@192.168.1.51>
In article <····························@posting.google.com>,
·········@gmx.net (thelifter) wrote:

> Alain Picard <·······················@optushome.com.au> wrote in message
news:<··············@optushome.com.au>...
> > Ok, try this.  Forget the word "variable" for a moment.  There ARE no
> > "variables".  There are only symbols and values.  When you evaluate an
> 
> I just took a look at the language specification. It seems that the
> main problem is, that there is no definition for variable:

Sure there is.  Look in the glossary.

E.
From: Harald Hanche-Olsen
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <pcor8dmpfu2.fsf@thoth.math.ntnu.no>
+ ···@jpl.nasa.gov (Erann Gat):

| In article <····························@posting.google.com>,
| ·········@gmx.net (thelifter) wrote:
| 
| > I just took a look at the language specification. It seems that the
| > main problem is, that there is no definition for variable:
| 
| Sure there is.  Look in the glossary.

And even more importantly, follow the advice in the glossary entry:
See Section 3.1.2.1.1 (Symbols as Forms) - where you find this crucial
piece of information:

  A variable can store one object. The main operations on a variable
  are to read[1] and to write[1] its value.

I think it's important to stop obsessing about what a variable /is/.
It's what you can /do/ with it that counts.  In a very real sense, the
variable is what it does, neither more nor less.

Here is an analogy from mathematics.  What is a number?  Well, who
cares?  Those who are concerned with the foundations of mathematics
care, that's who.  The rest of us just /use/ the bloody things.  Peano
understood this very well, so he listed a basic set of axioms for the
natural numbers, such as: 0 is a number; every number has a unique
successor; every number other than 0 is the successor of some unique
number.  Add the induction principle, and voila, you have the natural
numbers (modulo some nasty surprises concerning non-standard models
and such).  Only if you worry about such esoterica as how to construct
the natural numbers given nothing more than set theory do you dream up
seemingly crazy schemes such as 0={} (the empty set), 1={0}, 2={0,1},
etc.

Just like you only need to know how to compute with numbers, even if
you don't know what they are, so do you only need to know what to do
with variables: You can /read/ and /write/ them.  That is, a variable
is a certain place which will hold a value.  You put a value there,
and it remains until you put a different value in the same place by
assignment.  And you can look at the variable at any time (so long as
it's accessible) and find out what that value is.  And that's it, she
wrote.

Except there are other kinds of places: The fifth entry of a vector or
the CAR of a CONS are places too, but they are not variables.
Variables have another feature: They have /names/, and they are
accessible /only/ via their name.  That is why the HyperSpec says a
variable is a special kind of binding, which in its turn is an
association of a name with something: You can think of that something
as the /place/ which holds the variable's value, but really the only
important thing to know about it is its ability to remember a value
for later access.

In this example there are two variables, both named x:

(let ((x :outer))			; creates a new binding
  (format t "~&(1) x=~A~%" x)
  (setf x 42)				; same binding, new value
  (format t "~&(2) x=~A~%" x)
  (let ((x :inner))		        ; new binding, shadowing the old
    (format t "~&(3) x=~A~%" x))
  ;; The new binding is gone, leaving the old one visible once more
  (format t "~&(4) x=~A~%" x))

One variable has the values :OUTER and then 42.  The other one only
ever has the value :INNER.

In summary, then, a variable is a named place.  It is accessible only
through its name, and all you can do with it is set and look at its
value.  Since an object is defined by what it can do, this defines
variables.  The fact that a single name can denote different variables
at different times does not change this simple fact.

Gee, I set out to make a simple point (what you do is what you are)
and ended up writing a minor lecture.  It's an occupational hazard
with us academic types, I guess.  We get carried away by hearing
ourselves talk.  (In this case, it must be the sound of the keyboard
that has some hypnotic effect.)

-- 
* Harald Hanche-Olsen     <URL:http://www.math.ntnu.no/~hanche/>
- Yes it works in practice - but does it work in theory?
From: Nils Goesche
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <87ptt6cr3a.fsf@darkstar.cartan>
Harald Hanche-Olsen <······@math.ntnu.no> writes:

> I think it's important to stop obsessing about what a variable
> /is/.  It's what you can /do/ with it that counts.  In a very
> real sense, the variable is what it does, neither more nor
> less.
> 
> Here is an analogy from mathematics.  What is a number?  Well,
> who cares?  Those who are concerned with the foundations of
> mathematics care, that's who.  The rest of us just /use/ the
> bloody things.  Peano understood this very well, so he listed a
> basic set of axioms for the natural numbers, such as: 0 is a
> number; every number has a unique successor; every number other
> than 0 is the successor of some unique number.  Add the
> induction principle, and voila, you have the natural numbers
> (modulo some nasty surprises concerning non-standard models and
> such).

And some more real surprises, too:

  http://mathworld.wolfram.com/GoodsteinsTheorem.html

The Peano axioms are actually not enough do properly reflect our
notion of natural numbers, surprising as it seems.

> Only if you worry about such esoterica as how to construct the
> natural numbers given nothing more than set theory do you dream
> up seemingly crazy schemes such as 0={} (the empty set), 1={0},
> 2={0,1}, etc.

I don't see what's crazy about that.  It is nice that we can
define natural numbers like this and then prove the Peano axioms.
It is also very natural, rather than crazy: Every natural number
n defined in this way is a set with exactly n elements.  I like
that.

The question ``What /is/ a variable, after all?�� is likewise
interesting.  However, I agree that one shouldn't put so much
emphasis to it when it confuses somebody.

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

PGP key ID #xD26EF2A0
From: Erann Gat
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <gat-1611020852190001@192.168.1.51>
In article <··············@darkstar.cartan>, Nils Goesche <···@cartan.de> wrote:

> The question ``What /is/ a variable, after all?�� is likewise
> interesting.

Indeed.

The standard says:

A variable is a binding in the variable namespace.
A binding is an association between a name and that which the name denotes.
A namespace is [a set of] bindings whose denotations are restricted to a
particular kind.


My latest attempt to distill this for a revised version of TIG2SV:

A variable is a storage location that has a name.  (Or a variant suggested
by Len Charest: a variable is a storage location that is identified by an
identifier.)

E.


---

<tangent>

On a challenge from Crispin Sartwell's website I once took a stab at
trying to define the word "seven".  Here's what I came up with FWIW:


ZERO is a description of the non-existence of things.  It is usually
applied to a particular kind of thing defined by a particular set of
properties within a particular context.  "There are zero cows in my
office" means that within the context of my office there does not exist a
thing with the set of properties for which we use the shorthand notation
"cow".

ONE is a description of a particular kind of existence characterized by
the following property: there exists ONE (thing) if and only if it is not
possible to partition it into a subset and its complement such that both
the subset and its complement have the properties that define it.  If you
have ONE cow then it is not possible to partition that cow into a subset
and its complement such that both the subset and its complement are cows.

Note that this partitioning is a *mental* partitioning, not a physical
one.  This allows us to, for example, take a collection of cows and call
it ONE herd of cows by stipulating that one of the essential properties
that defines a herd is that it have a boundary beyond which there are no
cows.

TWO is a description of a particular kind of existence characterized by
the following property: there exist TWO (things) if and only if it is
possible to partition the context within which they exist into a subset
and its complement such that there is ONE in the subset and ONE in the
complement.

Note that there is an asymmetry here.  To decide whether there is ONE of
something you have to partition the THING, but to decide whether there is
TWO of something you have to partition the CONTEXT.  Thus, for some
collections of cows, it can be correct to say that there is both ONE and
TWO herds of cows depending on exactly how you choose to define a herd.

In general, if it is possible to partition a context such that there are X
in the subset and Y in the complement then we say that there exist X PLUS
Y.  Thus, TWO is ONE PLUS ONE.  THREE is TWO PLUS ONE (which is the same
as ONE PLUS ONE PLUS ONE) etc.  Seven is three plus two plus two.
From: Nils Goesche
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <87smy1761h.fsf@darkstar.cartan>
···@jpl.nasa.gov (Erann Gat) writes:

> In article <··············@darkstar.cartan>, Nils Goesche <···@cartan.de> wrote:
> 
> > The question ``What /is/ a variable, after all?�� is likewise
> > interesting.
> 
> Indeed.
> 
> The standard says:
> 
> A variable is a binding in the variable namespace.
> A binding is an association between a name and that which the name denotes.
> A namespace is [a set of] bindings whose denotations are restricted to a
> particular kind.
> 
> 
> My latest attempt to distill this for a revised version of TIG2SV:
> 
> A variable is a storage location that has a name.  (Or a
> variant suggested by Len Charest: a variable is a storage
> location that is identified by an identifier.)

Quite good.  I would like to be able to say ``A binding is an
association between a name and a storage location.��  This takes
into account that the same name can denote different locations in
different contexts.  A variable would simply be a name, then, I
guess.

> <tangent>
> 
> On a challenge from Crispin Sartwell's website I once took a
> stab at trying to define the word "seven".  Here's what I came
> up with FWIW:

Heh, nice.  Call me weird, but I think that nothing can beat the
poetic beauty of the correct answer, though:

(defun define (n)
  (labels ((pprint-k (n)
             (pprint-logical-block (nil nil :prefix "{" :suffix "}")
               (dotimes (i n)
                 (pprint-k i)
                 (when (< i (1- n))
                   (write-string ", ")
                   (pprint-newline :fill))))))
    (let ((*print-pretty* t)
          (*print-right-margin* 72))
      (pprint-k n))
    (values)))

CL-USER 15 > (define 7)
{{}, {{}}, {{}, {{}}}, {{}, {{}}, {{}, {{}}}},
 {{}, {{}}, {{}, {{}}}, {{}, {{}}, {{}, {{}}}}},
 {{}, {{}}, {{}, {{}}}, {{}, {{}}, {{}, {{}}}},
  {{}, {{}}, {{}, {{}}}, {{}, {{}}, {{}, {{}}}}}},
 {{}, {{}}, {{}, {{}}}, {{}, {{}}, {{}, {{}}}},
  {{}, {{}}, {{}, {{}}}, {{}, {{}}, {{}, {{}}}}},
  {{}, {{}}, {{}, {{}}}, {{}, {{}}, {{}, {{}}}},
   {{}, {{}}, {{}, {{}}}, {{}, {{}}, {{}, {{}}}}}}}}

:-)

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

PGP key ID #xD26EF2A0
From: Gareth McCaughan
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <slrnate700.hlo.Gareth.McCaughan@g.local>
Nils Goesche wrote:

>  Heh, nice.  Call me weird, but I think that nothing can beat the
>  poetic beauty of the correct answer, though:
>  
>  (defun define (n)
>    (labels ((pprint-k (n)
>               (pprint-logical-block (nil nil :prefix "{" :suffix "}")
>                 (dotimes (i n)
>                   (pprint-k i)
>                   (when (< i (1- n))
>                     (write-string ", ")
>                     (pprint-newline :fill))))))
>      (let ((*print-pretty* t)
>            (*print-right-margin* 72))
>        (pprint-k n))
>      (values)))
>  
>  CL-USER 15 > (define 7)
>  {{}, {{}}, {{}, {{}}}, {{}, {{}}, {{}, {{}}}},
>   {{}, {{}}, {{}, {{}}}, {{}, {{}}, {{}, {{}}}}},
>   {{}, {{}}, {{}, {{}}}, {{}, {{}}, {{}, {{}}}},
>    {{}, {{}}, {{}, {{}}}, {{}, {{}}, {{}, {{}}}}}},
>   {{}, {{}}, {{}, {{}}}, {{}, {{}}, {{}, {{}}}},
>    {{}, {{}}, {{}, {{}}}, {{}, {{}}, {{}, {{}}}}},
>    {{}, {{}}, {{}, {{}}}, {{}, {{}}, {{}, {{}}}},
>     {{}, {{}}, {{}, {{}}}, {{}, {{}}, {{}, {{}}}}}}}}

That's not "the correct answer", any more than the correct
answer to "What is a symbol?" is something like

    struct Symbol {
      LispObject * package;
      LispObject * name;
      LispObject * value;
    };

In other words, it's one implementation of the number 7
(better: it's the number 7 in one implementation of the
natural numbers). There are others, such as {{{{{{{{}}}}}}}}
and { x : |x| = 7 } (er, obviously the latter won't do as it
stands; it also won't work in ZF set theory, but it's fine
in something like NF).

ObLisp:

(defstruct box x0 y0 x1 y1 children bordered)

(defun box-size (b)
  (values (- (box-x1 b) (box-x0 b))
          (- (box-y1 b) (box-y0 b))))

(defun box-translate (b dx dy)
  (make-box :x0 (+ (box-x0 b) dx)
            :y0 (+ (box-y0 b) dy)
            :x1 (+ (box-x1 b) dx)
            :y1 (+ (box-y1 b) dy)
            :children (loop for child in (box-children b)
                            collect (box-translate child dx dy))
            :bordered (box-bordered b)))

(defun box-translate-to (b x y)
  (box-translate b (- x (box-x0 b)) (- y (box-y0 b))))

(defun box-surround (b delta)
  (make-box :x0 (- (box-x0 b) delta)
            :y0 (- (box-y0 b) delta)
            :x1 (+ (box-x1 b) delta)
            :y1 (+ (box-y1 b) delta)
            :children (list b)
            :bordered nil))

(defun bordered (b) (setf (box-bordered b) t) b)

(defun box-adjoin (b1 b2 delta direction)
  (multiple-value-bind (x1 y1) (box-size b1)
    (multiple-value-bind (x2 y2) (box-size b2)
      (ecase direction
        ((:h)
         (make-box :x0 0 :y0 0
                   :x1 (+ x1 x2 (* 3 delta))
                   :y1 (+ (max y1 y2) (* 2 delta))
                   :children (list (box-translate-to b1 delta delta)
                                   (box-translate-to b2 (+ x1 (* 2 delta)) delta))
                   :bordered nil))
        ((:v)
         (make-box :x0 0 :y0 0
                   :x1 (+ (max x1 x2) (* 2 delta))
                   :y1 (+ y1 y2 (* 3 delta))
                   :children (list (box-translate-to b1 delta delta)
                                   (box-translate-to b2 delta (+ y1 (* 2 delta))))
                   :bordered nil))))))

(defun flip (direction)
  (ecase direction
    ((:h) :v)
    ((:v) :h)))

(defun numerals (n size delta direction)
  (if (zerop n)
    (box-surround (make-box :x0 0 :y0 0 :x1 size :y1 size :bordered t) delta)
    (box-adjoin (numeral n size delta (flip direction))
                (numerals (1- n) size delta (flip direction))
                delta
                direction)))

(defun numeral (n size delta direction)
  (if (zerop n)
    (make-box :x0 0 :y0 0 :x1 size :y1 size :bordered t)
    (bordered (numerals (1- n) size delta direction))))

(defun flatten (b)
  (let ((rest (loop for child in (box-children b) nconc (flatten child))))
    (if (box-bordered b)
      (cons (list (box-x0 b) (box-y0 b) (box-x1 b) (box-y1 b)) rest)
      rest)))

(defun show-flattened (boxes dx dy &optional (stream t))
  (princ "%!PS
/box { /y1 exch def /x1 exch def /y0 exch def /x0 exch def
       x0 y0 moveto x1 y0 lineto x1 y1 lineto x0 y1 lineto closepath stroke }
     bind def
"  stream)
  (loop for (x0 y0 x1 y1) in boxes do
    (format stream "~A ~A ~A ~A box~%" (+ x0 dx) (+ y0 dy) (+ x1 dx) (+ y1 dy)))
  (princ "showpage
" stream))

(with-open-file (f "10.ps" :direction :output)
  (show-flattened (flatten (numeral 10 3 3 :v)) 30 30 f))

This is rather nasty code in several ways, but its output is
rather lovely.

-- 
Gareth McCaughan  ················@pobox.com
.sig under construc
From: Nils Goesche
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <87y97s4x2j.fsf@darkstar.cartan>
Gareth McCaughan <················@pobox.com> writes:

> Nils Goesche wrote:
> 
> >  Heh, nice.  Call me weird, but I think that nothing can beat the
> >  poetic beauty of the correct answer, though:
> >  
> >  {{}, {{}}, {{}, {{}}}, {{}, {{}}, {{}, {{}}}},
> >   {{}, {{}}, {{}, {{}}}, {{}, {{}}, {{}, {{}}}}},
> >   {{}, {{}}, {{}, {{}}}, {{}, {{}}, {{}, {{}}}},
> >    {{}, {{}}, {{}, {{}}}, {{}, {{}}, {{}, {{}}}}}},
> >   {{}, {{}}, {{}, {{}}}, {{}, {{}}, {{}, {{}}}},
> >    {{}, {{}}, {{}, {{}}}, {{}, {{}}, {{}, {{}}}}},
> >    {{}, {{}}, {{}, {{}}}, {{}, {{}}, {{}, {{}}}},
> >     {{}, {{}}, {{}, {{}}}, {{}, {{}}, {{}, {{}}}}}}}}
> 
> That's not "the correct answer", any more than the correct
> answer to "What is a symbol?" is something like
> 
>     struct Symbol {
>       LispObject * package;
>       LispObject * name;
>       LispObject * value;
>     };
> 
> In other words, it's one implementation of the number 7
> (better: it's the number 7 in one implementation of the
> natural numbers). There are others, such as {{{{{{{{}}}}}}}}
> and { x : |x| = 7 } (er, obviously the latter won't do as it
> stands; it also won't work in ZF set theory, but it's fine
> in something like NF).

I know.  I meant it is my favorite among the correct answers.
And it is certainly the most poetic ;-)

> (with-open-file (f "10.ps" :direction :output)
>   (show-flattened (flatten (numeral 10 3 3 :v)) 30 30 f))
> 
> This is rather nasty code in several ways, but its output is
> rather lovely.

Very cool indeed.  Thanks for this!

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

PGP key ID #xD26EF2A0
From: Gareth McCaughan
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <slrnato8k4.s0v.Gareth.McCaughan@g.local>
I wrote:

>  ObLisp:
>  
>  (defstruct box x0 y0 x1 y1 children bordered)

[...]

>  (with-open-file (f "10.ps" :direction :output)
>    (show-flattened (flatten (numeral 10 3 3 :v)) 30 30 f))
>  
>  This is rather nasty code in several ways, but its output is
>  rather lovely.

I have one of these sitting on my desk with n=14 (suggested
parameters: (NUMERAL 14 0.75 0.75 :V) and insert
"0.24 setlinewidth" in an appropriate place in the
generated PostScript file), and it just occurred to me
to de-converge my eyes and treat it as an autostereogram.
To my considerable surprise, this sort-of worked. I'm
having trouble working out *how* it works, since the
defining feature of an autostereogram (corresponding
features being displaced relative to one another) isn't
present: the difference between the repeating units is
in the presence or absence of features, not displacement.

Can someone who understands these things better than me
explain what's going on here? I'm sure I'm missing something
obvious.

-- 
Gareth McCaughan  ················@pobox.com
.sig under construc
From: Nils Goesche
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <87d6oztyyh.fsf@darkstar.cartan>
Gareth McCaughan <················@pobox.com> writes:

> I have one of these sitting on my desk with n=14 (suggested
> parameters: (NUMERAL 14 0.75 0.75 :V) and insert "0.24
> setlinewidth" in an appropriate place in the generated
> PostScript file), and it just occurred to me to de-converge my
> eyes and treat it as an autostereogram.  To my considerable
> surprise, this sort-of worked. I'm having trouble working out
> *how* it works, since the defining feature of an autostereogram
> (corresponding features being displaced relative to one
> another) isn't present: the difference between the repeating
> units is in the presence or absence of features, not
> displacement.
> 
> Can someone who understands these things better than me explain
> what's going on here? I'm sure I'm missing something obvious.

I think the right person to ask in this case is Timothy Leary.

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

PGP key ID #xD26EF2A0
From: Gareth McCaughan
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <slrnatolnp.s0v.Gareth.McCaughan@g.local>
Nils Goesche wrote:
>  Gareth McCaughan <················@pobox.com> writes:
>  
> > I have one of these sitting on my desk with n=14 (suggested
> > parameters: (NUMERAL 14 0.75 0.75 :V) and insert "0.24
> > setlinewidth" in an appropriate place in the generated
> > PostScript file), and it just occurred to me to de-converge my
> > eyes and treat it as an autostereogram.  To my considerable
> > surprise, this sort-of worked. I'm having trouble working out
> > *how* it works, since the defining feature of an autostereogram
> > (corresponding features being displaced relative to one
> > another) isn't present: the difference between the repeating
> > units is in the presence or absence of features, not
> > displacement.
> > 
> > Can someone who understands these things better than me explain
> > what's going on here? I'm sure I'm missing something obvious.
>  
>  I think the right person to ask in this case is Timothy Leary.

I promise you, my investigations were, um, unaided. :-)

Anyway: I'm a twit, and it's very simple. It's not true that
there are no displacements; repeating units are closer together
physically when they have a more recent common ancestor in the
obvious tree. I'm not quite sure why I thought this wasn't so,
but I was dead wrong anyway.

-- 
Gareth McCaughan  ················@pobox.com
.sig under construc
From: Harald Hanche-Olsen
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <pcon0o9ptxn.fsf@thoth.math.ntnu.no>
+ Nils Goesche <···@cartan.de>:

| Harald Hanche-Olsen <······@math.ntnu.no> writes:
| 
| > Only if you worry about such esoterica as how to construct the
| > natural numbers given nothing more than set theory do you dream
| > up seemingly crazy schemes such as 0={} (the empty set), 1={0},
| > 2={0,1}, etc.
| 
| I don't see what's crazy about that.

Neither do I, which is why I wrote "seemingly".  But when I was first
exposed to the idea, way back in the mists of time, I did think it was
crazy, at least until the idea began to sink in and I realized the
elegance of it all (as you describe so eloquently).

| The question ``What /is/ a variable, after all?�� is likewise
| interesting.

Even more so in mathematics than in computing, methinks.  I have never
understood why the induction principle seems to be so difficult to
grasp, but it is an observable fact that many students fail to get
it.  Actually, I think it is not the induction principle /per se/ that
confuses people, but that they have a more fundamental problem in
understanding what mathematics is all about, and in particular in
grasping the notion of a variable.  If you haven't got a firm grip on
that, a proof by induction really seems circular, and so the students
are left wondering why they are told not to employ circular reasoning,
and yet, within the framework of induction, it is OK to do so?

I think the situation is very similar with respect to the notion of
variables in Lisp.  Once you get it, it is blindingly obvious, but
when you try to explain this insight, you're still groping for words.
(And personally, I find I still struggle with the terminology, as
evidenced by an earlier posting of mine in this thread.)

-- 
* Harald Hanche-Olsen     <URL:http://www.math.ntnu.no/~hanche/>
- Yes it works in practice - but does it work in theory?
From: Alain Picard
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <87smy2cb4a.fsf@optushome.com.au>
·········@gmx.net (thelifter) writes:

> Alain Picard <·······················@optushome.com.au> wrote in message news:<··············@optushome.com.au>...
> > Ok, try this.  Forget the word "variable" for a moment.  There ARE no
> > "variables".  There are only symbols and values.  When you evaluate an
> 
> I just took a look at the language specification. It seems that the
> main problem is, that there is no definition for variable:

Please understand that I offered this explanation in the context
of a guide "for idiots" (God I hate that term).  Of course there
_are_ variables, both in execution and in the spec---refer to Kent's
reply to my previous post to see what that's all about.

But if you want to get a temporary mental model for how things
work, I offered you one.  It's, by design, incomplete and inaccurate.

 
From: Kent M Pitman
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <sfwheeij3x9.fsf@shell01.TheWorld.com>
Alain Picard <·······················@optushome.com.au> writes:

> ·········@gmx.net (thelifter) writes:
> 
> > ···@jpl.nasa.gov (Erann Gat) wrote in message 
> > news:<····················@k-137-79-50-101.jpl.nasa.gov>...
> > 
> > > But they aren't.  Variables and symbols are two different things.
> > 
> > That's one of the things I don't understand, can you explain me the
> > difference please or give a good pointer(Sorry, I'm just an idiot)?
> 
> Ok, try this.  Forget the word "variable" for a moment.  There ARE no
> "variables".  There are only symbols and values.  When you evaluate an
> expression, and that expression happens to be a symbol, you need to
> fetch the value currently _bound_ to that symbol.  Values are bound to
> symbols using, funnily enough, binding establishing forms [the most
> common of which is LET].
> 
> Bindings are looked up either lexically or dynamically, depending on
> whether the symbol being looked up is known to be _special_ in the
> context for which the evaluation is proceeding.
> 
> Now, does that help, or merely confuse even more?

It just confuses things more.

The evaluation of an expression is best understood in two steps:
identification of variables from among the symbols, and then 
operation on variables.

The fact that symbols have values is a red herring that is best 
ignored for the purpose of understanding symbols, since those values
might or might not relate to the value of the variable which the symbol
might or might not denote.

Only variables have [lexical] values.  Symbols do not.

Some symbols are used as identifiers to denote variables, but not all
symbols are identifiers denoting variables.  Not even all symbols in
evaluable positions are.  (Consider symbol macros.)

I think the best way to think about evaluation is to think in terms of
classifying each of the "objects" in the surface syntax into programmatic
meta structures such as "forms".  This is why the distinction is made
in the stnadard between "expressions" (which are data with no applied
semantics) and "forms" (which are data, a subset of the data that are
expressions, intended to be viewed specifically as programs).

The classification phase is something the compiler does as part of
compilation, while the association of variables with values is
something that is done by the runtime/execution phase of the system.
Describing variables by appealing to the original structures seems
wrong to me becuase it appears to suggest that the language processor
will repeatedly revert to an understanding of the symbols that is
pre-classification; while it is free to use such a technique, most
compilers do not and I believe even most interpreters do not.  EVAL is
confusing to people because it potentially interleaves these two
processes (though in more extant implementations I believe it just
calls the two processes in rapid succession, that is, it funcalls the
result of a quick compilation).

After classification, it is variables that have [lexical] values, and not
symbols.  Even for dynamic variables, which are classified as well, it
is pure coincidence that 
  (symbol-value '*identifier-that-originally-named-the-variable-that-is-now-seen-to-have-been-a-special-variable*)
happens to return the same value as 
  *identifier-that-originally-named-the-variable-that-is-now-seen-to-have-been-a-special-variable*
and no great harm (other than a loss of backward compatibility) would come
if we simply removed SYMBOL-VALUE from the language.  We leave SYMBOL-VALUE
in place because [a] we think backward compatibility is good and
[b] there is some cool punning to be done BY PEOPLE WHO HAVE A FIRM GRASP
OF THE PUNNING THEY ARE DOING.

Punning means that two UNRELATED facilities are being overlapped out of
"felicity", that is, a coincidence is being exploited.  This happens to be
coincidence-by-design, but it certainly does not appear in other languages
that have notions of specialness and so is not a necessary part of the
specification of specialness.   

Because the symbol-valueness is only entirely coincidental, many of us in the
community cringe any time anyone describes a "variable" as having any relation
to a symbol.

I once [in a rejected early design document for the T language] proposed a
special form VAR which allowed one to write

 (LAMBDA (1 2) (+ (VAR 1) (VAR 2)))

In this notation, anything, not just a symbol could be a variable name.
In this notation, you can clearly see that the symbolness of variables 
is just a convenient accident and that 

 (LAMBDA (X Y) (+ X Y))

is just shorthand for

 (LAMBDA (X Y) (+ (VAR X) (VAR Y)))

or more precisely in the proposal I'd made, which used all special [compound]
forms and no atomic forms at all [other than shorthands]:

 (LAMBDA (X Y) (CALL (VAR +) (VAR X) (VAR Y)))

to distinguish from what I imagined would be CL's

 (LAMBDA (X Y) (CALL (VAR + FUNCTION) (VAR X VALUE) (VAR Y VALUE)))

If you understand the language in this way, you will better understand
why symbols have nothing to do with lexical variables, since you could quite
easily find yourself without symbols and with no panic over why none of the
symbol operations are available.  Lexical variable values are managed at
a level of processing in the interpreter, they are not managed in the data
structure that syntactically identified the variable to the system.

Indeed, if you have this mechanism clear in your head it makes it easier
to see why it's ok to do DEFUN on non-symbols like (SETF FOO), so that

 (FUNCALL #'(SETF FILLER) NEW X Y)

is seen as meaning

 (CALL (VAR (SETF FILLER) FUNCTION) 
       (VAR NEW VALUE)
       (VAR X VALUE)
       (VAR Y VALUE))

and in this way you just see that (SETF FILLER) just has to be a valid
key to the namespace whose key is FUNCTION, and you don't find yourself
obsessing about whether it has a SYMBOL-VALUE.  [Indeed, you find yourself
with a different and more rational set of concerns like whether the name
is compared by EQ or EQL or EQUAL or EQUALP, hopefully deciding on EQUAL
because that makes the Lisp universe appear most rational, IMO.]

This notation is part of a project I have half-completed for unifying the
Lisp and Scheme worlds by eliminating the messy business of fighting over
the car of the "form".  That's such a syntactic matter, and again gets
back to the issue of why programming language semantics is not well
explained by appealing back to the syntax; the language definition of
Scheme always should have been in terms of special forms only, and it's quite
bizarre that the two most-used special forms [CALL and VAR] have no name
but rather are expressed only in terms of program shape.  That's great
shorthand for a particular notational processor, just like it's handy to
have 7 mean the same as (QUOTE 7), but such syntactic cutenesses have no
business wending their way down to the semantics.
From: Erann Gat
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <gat-1511020905310001@192.168.1.51>
In article <···············@shell01.TheWorld.com>, Kent M Pitman
<······@world.std.com> wrote:

> Because the symbol-valueness is only entirely coincidental, many of us in the
> community cringe any time anyone describes a "variable" as having any relation
> to a symbol.

You must cringe when you read the hyperspec (which is supremely ironic
considering that you wrote it!)  Here's what the spec has to say about
variables:

<quote>

variable n. a binding in the ``variable'' namespace. See Section 3.1.2.1.1
(Symbols as Forms).

...

3.1.2.1.1 Symbols as Forms

If a form is a symbol, then it is either a symbol macro or a variable. 

...

If a form is a symbol that is not a symbol macro, then it is the name of a
variable, and the value of that variable is returned.

</quote>

So the spec is quite clear that a variable has some relation to a symbol. 
That relationship is in fact precisely what I say in my guide: symbols are
the names of variables.

E.
From: Erik Naggum
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <3246379378547120@naggum.no>
* Erann Gat -> Kent Pitman
| You must cringe when you read the hyperspec (which is supremely ironic
| considering that you wrote it!)

  Gee, that was constructive.

-- 
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.
From: Kent M Pitman
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <sfwheeieb5a.fsf@shell01.TheWorld.com>
···@jpl.nasa.gov (Erann Gat) writes:

> <quote>
> 
> variable n. a binding in the ``variable'' namespace. See Section 3.1.2.1.1
> (Symbols as Forms).
> 
> ...
> 
> 3.1.2.1.1 Symbols as Forms
> 
> If a form is a symbol, then it is either a symbol macro or a variable. 
> 
> ...
> 
> If a form is a symbol that is not a symbol macro, then it is the name of a
> variable, and the value of that variable is returned.
> 
> </quote>
> 
> So the spec is quite clear that a variable has some relation to a symbol. 
> That relationship is in fact precisely what I say in my guide: symbols are
> the names of variables.

No, the names of variables are symbols.

Symbols are either variables or symbol macros.
From: Erann Gat
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <gat-1511021625510001@k-137-79-50-101.jpl.nasa.gov>
In article <···············@shell01.TheWorld.com>, Kent M Pitman
<······@world.std.com> wrote:

> ···@jpl.nasa.gov (Erann Gat) writes:
> > symbols are the names of variables.
> 
> No, the names of variables are symbols.

Seems like splitting hairs to me.

> Symbols are either variables or symbol macros.

Sure, but that doesn't change the fact that symbols are (sometimes - in
fact usually, but not always) the names of variables.

E.
From: Adam Warner
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <pan.2002.11.16.01.12.33.431393@consulting.net.nz>
Hi Erann Gat,

> In article <···············@shell01.TheWorld.com>, Kent M Pitman
> <······@world.std.com> wrote:
> 
>> ···@jpl.nasa.gov (Erann Gat) writes:
>> > symbols are the names of variables.
>> 
>> No, the names of variables are symbols.
> 
> Seems like splitting hairs to me.

There is no splitting hairs. It is logic/set theory. You stated
"...precisely what I say in my guide: symbols are the names of variables."
This reasonably reads that all symbols are the names of variables. Kent
switched this around so that all names of variables are symbols. All names
of variables are symbols but not all symbols are not names of variables.

>> Symbols are either variables or symbol macros.
> 
> Sure, but that doesn't change the fact that symbols are (sometimes - in
> fact usually, but not always) the names of variables.

Please express this as the names of variables are symbols. You just wrote
that symbols are or are not the names of variables. That's not very
useful.

Regards,
Adam
From: Erann Gat
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <gat-1511022133200001@192.168.1.51>
In article <······························@consulting.net.nz>, "Adam
Warner" <······@consulting.net.nz> wrote:

> There is no splitting hairs. It is logic/set theory.

Are you kidding?  That's the very definition of splitting hairs!

E.
From: Erann Gat
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <gat-1511021412190001@k-137-79-50-101.jpl.nasa.gov>
In article <···············@shell01.TheWorld.com>, Kent M Pitman
<······@world.std.com> wrote:

>  Even for dynamic variables, which are classified as well, it
> is pure coincidence that 
>   (symbol-value
'*identifier-that-originally-named-the-variable-that-is-now-seen-to-have-been-a-special-variable*)
> happens to return the same value as 
>  
*identifier-that-originally-named-the-variable-that-is-now-seen-to-have-been-a-special-variable*

No, it's not a coincidence, it's required by the standard:

Accessor SYMBOL-VALUE 
...
Accesses the symbol's value cell. 

value cell n. Trad. (of a symbol) The place which holds the value, if any,
of the dynamic variable named by that symbol, and which is accessed by
symbol-value.

> and no great harm (other than a loss of backward compatibility) would come
> if we simply removed SYMBOL-VALUE from the language.

Really?  How would you obtain the value of symbols whose identities were
not known until run-time?

[Long argument snipped]

This is a pedagogical argument, and I actually agree with you that things
would be clearer if they were explained this way.  Unfortunately, that is
not the way things are.  The CL standard unambiguously identifies
variables with symbols.  That this causes confusion I do not dispute; that
was, in fact, one of the motivations for writing "The idiot's guide..."

This is one of many areas where, IMO, CL would do well to clean house.

E.
From: Nils Goesche
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <87u1iictte.fsf@darkstar.cartan>
···@jpl.nasa.gov (Erann Gat) writes:

> In article <···············@shell01.TheWorld.com>, Kent M Pitman
> <······@world.std.com> wrote:
> 
> > and no great harm (other than a loss of backward
> > compatibility) would come if we simply removed SYMBOL-VALUE
> > from the language.
> 
> Really?  How would you obtain the value of symbols whose identities were
> not known until run-time?

My magic: Evaluate them.

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

PGP key ID #xD26EF2A0
From: Erann Gat
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <gat-1511021639500001@k-137-79-50-101.jpl.nasa.gov>
In article <··············@darkstar.cartan>, Nils Goesche <···@cartan.de> wrote:

> ···@jpl.nasa.gov (Erann Gat) writes:
> 
> > In article <···············@shell01.TheWorld.com>, Kent M Pitman
> > <······@world.std.com> wrote:
> > 
> > > and no great harm (other than a loss of backward
> > > compatibility) would come if we simply removed SYMBOL-VALUE
> > > from the language.
> > 
> > Really?  How would you obtain the value of symbols whose identities were
> > not known until run-time?
> 
> My magic: Evaluate them.

There are two interpretations of the claim that "no great harm ... would
come if we simply remove symbol-value from the language."

The first interpretation is that removing symbol-value would cause no
great harm because it can simply be added back again thusly:

(defun symbol-value (symbol)
  (if (symbolp symbol) (eval symbol) (error "~S is not a symbol" symbol)))

but that seemed like a pretty uninintersting observation to me, so I
assumed that this was not Kent's intention (particularly since the claim
was made in the context of a discussion of how associating variables and
symbols is just wrong).

I assumed he meant something deeper: no great harm would come if we
eliminated the functionality that symbol-value provides, under whatever
guises that functionality exists in the language (including the ability to
evaluate symbols at run time).

E.
From: Nils Goesche
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <87heeich36.fsf@darkstar.cartan>
···@jpl.nasa.gov (Erann Gat) writes:

> In article <··············@darkstar.cartan>, Nils Goesche <···@cartan.de> wrote:
> 
> > ···@jpl.nasa.gov (Erann Gat) writes:
> > 
> > > In article <···············@shell01.TheWorld.com>, Kent M Pitman
> > > <······@world.std.com> wrote:
> > > 
> > > > and no great harm (other than a loss of backward
> > > > compatibility) would come if we simply removed SYMBOL-VALUE
> > > > from the language.
> > > 
> > > Really?  How would you obtain the value of symbols whose identities were
> > > not known until run-time?
> > 
> > My magic: Evaluate them.
> 
> There are two interpretations of the claim that "no great harm ... would
> come if we simply remove symbol-value from the language."
> 
> The first interpretation is that removing symbol-value would cause no
> great harm because it can simply be added back again thusly:
> 
> (defun symbol-value (symbol)
>   (if (symbolp symbol) (eval symbol) (error "~S is not a symbol" symbol)))

Sure, but the more interesting case is how you would bring
(SETF SYMBOL-VALUE) back.  Remember that much of this discussion
came from the confusion about when or when not (setq x y) and
(setf (symbol-value 'x) y) can be used interchangably.

> but that seemed like a pretty uninintersting observation to me,
> so I assumed that this was not Kent's intention (particularly
> since the claim was made in the context of a discussion of how
> associating variables and symbols is just wrong).

It is interesting insofar as it emphasizes that you don't need
SYMBOL-VALUE to understand variables in Common Lisp, I think.

> I assumed he meant something deeper: no great harm would come
> if we eliminated the functionality that symbol-value provides,
> under whatever guises that functionality exists in the language
> (including the ability to evaluate symbols at run time).

It would very surprise me if that was what he meant.

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

PGP key ID #xD26EF2A0
From: Erann Gat
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <gat-1511022130380001@192.168.1.51>
In article <··············@darkstar.cartan>, Nils Goesche <···@cartan.de> wrote:

> Sure, but the more interesting case is how you would bring
> (SETF SYMBOL-VALUE) back.

<shrug>

(defun (setf symbol-value) (value symbol)
  (set symbol value))

or if that was too cute

(defun (setf symbol-value) (value symbol)
  (eval `(locally (declare (special ,symbol)) (setq ,symbol ,value))))

> It is interesting insofar as it emphasizes that you don't need
> SYMBOL-VALUE to understand variables in Common Lisp, I think.

You don't need the symbol-value function, but I don't see how you can
understand variables in CL without the *concept* of a symbol's value (or
its dynamic binding or whatever you want to call it).

BTW, a number of people have written to me to say that symbols have
nothing to do with lexical bindings.  This is false.  The semantics of
lexical bindings in Common Lisp are defined in such a way that a compiler
*may* optimize away the symbols, but the semantics of lexical variables
are defined in the standard in terms of symbols.  (Also, most
implementations keep the symbols around for debugging.)

E.
From: Nils Goesche
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <87vg2yau3m.fsf@darkstar.cartan>
···@jpl.nasa.gov (Erann Gat) writes:

> In article <··············@darkstar.cartan>, Nils Goesche <···@cartan.de> wrote:
> 
> > Sure, but the more interesting case is how you would bring
> > (SETF SYMBOL-VALUE) back.
> 
> <shrug>
> 
> (defun (setf symbol-value) (value symbol)
>   (set symbol value))
> 
> or if that was too cute
> 
> (defun (setf symbol-value) (value symbol)
>   (eval `(locally (declare (special ,symbol)) (setq ,symbol ,value))))

Ok, and the interesting part is that your code does not look like
it manipulates a data structure, anymore.  You are using only
abstract operators for setting variables.  I can achieve the same
thing in bash:

#!/bin/bash

set_symbol_value () {
        eval "$1=$2"
}

x=2

set_symbol_value x 4

echo $x

will output 4.  The values don't come from a symbol data
structure anymore but have to be explained purely semantically.

> > It is interesting insofar as it emphasizes that you don't
> > need SYMBOL-VALUE to understand variables in Common Lisp, I
> > think.
> 
> You don't need the symbol-value function, but I don't see how
> you can understand variables in CL without the *concept* of a
> symbol's value (or its dynamic binding or whatever you want to
> call it).

By not calling it the ``symbol's�� value.  Variables have values;
a symbol is just some arbitrary data structure.  Sure, Lisp code
is made up of conses and symbols, but as soon as it is
/evaluated/, it doesn't matter anymore what kind of thing a
symbol actually is and if it has something like a value slot or
not.  That's an implementation issue.  As soon as a symbol is
evaluated (and it is not a symbol macro ;-), it is used to denote
the /name/ of a /variable/.  The level of abstraction is higher.

> BTW, a number of people have written to me to say that symbols
> have nothing to do with lexical bindings.  This is false.  The
> semantics of lexical bindings in Common Lisp are defined in
> such a way that a compiler *may* optimize away the symbols, but
> the semantics of lexical variables are defined in the standard
> in terms of symbols.  (Also, most implementations keep the
> symbols around for debugging.)

This is just a variation of the above.

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

PGP key ID #xD26EF2A0
From: Erann Gat
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <gat-1611020047530001@192.168.1.51>
In article <··············@darkstar.cartan>, Nils Goesche <···@cartan.de> wrote:

> The values don't come from a symbol data structure anymore

But they never did.  Who said anything about a symbol data structure?

Here's another implementation of symbol-value:

(let ((env (make-hash-table)))
  (defun symbol-value (s) (gethash env s))
  (defun (setf symbol-value) (value s)
    (setf (gethash env s) value))))

Using this implementation you can set the symbol-value of any Lisp object,
not just symbols.

E.
From: Nils Goesche
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <87wund79lg.fsf@darkstar.cartan>
···@jpl.nasa.gov (Erann Gat) writes:

> In article <··············@darkstar.cartan>, Nils Goesche <···@cartan.de> wrote:
> 
> > The values don't come from a symbol data structure anymore
> 
> But they never did.  Who said anything about a symbol data
> structure?
> 
> Here's another implementation of symbol-value:
> 
> (let ((env (make-hash-table)))
>   (defun symbol-value (s) (gethash env s))
>   (defun (setf symbol-value) (value s)
>     (setf (gethash env s) value))))
> 
> Using this implementation you can set the symbol-value of any
> Lisp object, not just symbols.

Sure.  But the very notations (symbol-value 'x) or (setf
(symbol-value 'x) 42) look exactly as if somebody did a
(defstruct symbol ((value ...) ...) before.  We are talking about
conceptual models for describing the semantics of Lisp variables.
If you avoid, for the moment, the SYMBOL-VALUE way of accessing a
(dynamic) variable's value it becomes clearer, for beginners,
that this is about evaluation, scope and environments of
variables and that you can perfectly understand their behavior
without thinking of a symbol as a data structure with a slot that
contains the value of the variable it denotes (which would give
you the wrong idea for lexical variables, anyway).  As I said,
Lisp code is made up of symbols and conses (and other atoms!),
but as soon as we are trying to describe the semantics of the
/code/ this tree structure of objects /represents/, it is better
to get away as far as possible from the physical representation
of our code when we describe its /meaning/.  Once this has been
understood, and only then, we can get to the additional cutie
that we can /also/ access the /semantic/ value of a dynamic
variable by accessing a physical ``value�� slot of the symbol,
the data structure, that is used to represent it.

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

PGP key ID #xD26EF2A0
From: Kent M Pitman
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <sfwwunc16o8.fsf@shell01.TheWorld.com>
···@jpl.nasa.gov (Erann Gat) writes:

> I assumed he meant something deeper: no great harm would come if we
> eliminated the functionality that symbol-value provides, under whatever
> guises that functionality exists in the language (including the ability to
> evaluate symbols at run time).

(eval '*foo*) would still exist.
From: thelifter
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <b295356a.0211151457.3788e6c0@posting.google.com>
Kent M Pitman <······@world.std.com> wrote in message news:<···············@shell01.TheWorld.com>...
> After classification, it is variables that have [lexical] values, and not
> symbols.  Even for dynamic variables, which are classified as well, it
> is pure coincidence that 
>   (symbol-value '*identifier-that-originally-named-the-variable-that-is-now-seen-to-have-been-a-special-variable*)
> happens to return the same value as 
>   *identifier-that-originally-named-the-variable-that-is-now-seen-to-have-been-a-special-variable*

Well, according to the language specification this is no coincidence
but intended:
"symbol-value returns the current value of the dynamic (special)
variable named by symbol."

> and no great harm (other than a loss of backward compatibility) would come
> if we simply removed SYMBOL-VALUE from the language.  We leave SYMBOL-VALUE
> in place because [a] we think backward compatibility is good and
> [b] there is some cool punning to be done BY PEOPLE WHO HAVE A FIRM GRASP
> OF THE PUNNING THEY ARE DOING.

According to the language specification symbol-value is useful:

"This function is particularly useful for implementing interpreters
for languages embedded in Lisp. The corresponding assignment primitive
is set; alternatively, symbol-value may be used with setf. "

Sorry to say this, but your text couldn't diminish my confusion. Don't
worry, it's not your fault, remember that Eran Gatt wanted to write a
text for IDIOTS...

:))
From: Erik Naggum
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <3246396977288750@naggum.no>
* ·········@gmx.net (thelifter)
| Well, according to the language specification this is no coincidence
| but intended:
| "symbol-value returns the current value of the dynamic (special)
| variable named by symbol."

  Would you guys please try to /listen/ to what Kent says and not argue
  against it without understanding it?

  What you assume without due cause is that there has been a `special�
  declaration for the symbol.  This is the assumption that you have to
  understand does not always hold.

  My God, how annoying it is to try to explain something to people who are
  unwilling to listen because they believe they already understand things
  better than their teachers.

-- 
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.
From: Harald Hanche-Olsen
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <pcoisyxptkd.fsf@thoth.math.ntnu.no>
+ Erik Naggum <····@naggum.no>:

| My God, how annoying it is to try to explain something to people who
| are unwilling to listen because they believe they already understand
| things better than their teachers.

Yeah, but I still prefer the student who tells me I am wrong, as long
as he gives a reason for thinking so.  It is only if he persists after
his mistake has been pointed out to him that he becomes annoying.

I am not denying that this often happens on Usenet, of course.

-- 
* Harald Hanche-Olsen     <URL:http://www.math.ntnu.no/~hanche/>
- Yes it works in practice - but does it work in theory?
From: Kalle Olavi Niemitalo
Subject: KMP's no-atomic-forms proposal for T
Date: 
Message-ID: <87znsak4sj.fsf_-_@Astalo.y2000.kon.iki.fi>
Kent M Pitman <······@world.std.com> writes:

> or more precisely in the proposal I'd made, which used all special
> [compound] forms and no atomic forms at all [other than shorthands]:
> 
>  (LAMBDA (X Y) (CALL (VAR +) (VAR X) (VAR Y)))

How did you propose to handle macros?

- (MACRO-CALL (VAR AND) (VAR X) (VAR Y)): seems good enough.

- (CALL (VAR AND) (VAR X) (VAR Y)): requires further analysis at
  compile time to find out which VARs refer to macros, but the
  compiler has to locate the binding forms anyway, so perhaps
  it's easy.

- (AND (VAR X) (VAR Y)): it would then be difficult to have
  macros with names like CALL, and your proposal already made
  (VAR CALL) unambiguous so I assume you wanted to give the same
  freedom with macros.

- with a separate macro processor that translates to this syntax
  from something else.
From: Kent M Pitman
Subject: Re: KMP's no-atomic-forms proposal for T
Date: 
Message-ID: <sfwd6p6eav4.fsf@shell01.TheWorld.com>
Kalle Olavi Niemitalo <···@iki.fi> writes:

> Kent M Pitman <······@world.std.com> writes:
> 
> > or more precisely in the proposal I'd made, which used all special
> > [compound] forms and no atomic forms at all [other than shorthands]:
> > 
> >  (LAMBDA (X Y) (CALL (VAR +) (VAR X) (VAR Y)))
> 
> How did you propose to handle macros?

Substitute "syntactic shorthand" for "macro" and it will be easier to see.
 
(+ x y) is a syntactic shorthand.

So is a macro form.

> - (MACRO-CALL (VAR AND) (VAR X) (VAR Y)): seems good enough.

No, it's not needed.  Simply

 (AND X Y)

or

 (AND (VAR X) (VAR Y))

is appropriate.  You actually don't need to represent the macro call in 
the execution semantics because the execution semantics should have macros
removed.


> - (CALL (VAR AND) (VAR X) (VAR Y)): requires further analysis at
>   compile time to find out which VARs refer to macros, but the
>   compiler has to locate the binding forms anyway, so perhaps
>   it's easy.

No, no in my analysis.  This would be the way of saying to funcall whatever
was in the variable AND, whether or not that was a macro or special form
(which might or might not be funcallable).
 
> - (AND (VAR X) (VAR Y)): it would then be difficult to have
>   macros with names like CALL, and your proposal already made
>   (VAR CALL) unambiguous so I assume you wanted to give the same
>   freedom with macros.

You're confusing yourself by assuming there is no namespacing system.
I didn't outline the complete proposal and don't plan to.  It's quite
complicated to do this in full form and I don't want to go into why here.
I do havea  partly worked through implementation and namespacing either
by symbols or by lexical bindings is not a problem.  But it involves
additional primitives.  I only specified the primitives needed to make a
specific point in this conversation--you don't have enough foundation to
either approve or disapprove my full proposal here and I don't have enough
time to really present/defend it.

> - with a separate macro processor that translates to this syntax
>   from something else.

This is the same as the previous bullet item, as far as I'm concerned, and
both work.
From: Nils Goesche
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <87vg2zttzr.fsf@darkstar.cartan>
···@jpl.nasa.gov (Erann Gat) writes:

> 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
From: sv0f
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <none-1511021529090001@129.59.212.53>
In article <··············@darkstar.cartan>, Nils Goesche <···@cartan.de> wrote:

>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.

"My propositions serve as elucidations in the following way:
anyone who understand me eventually recognizes them as
nonsensical, when he has used them � as steps � to climb beyond
them. (He must, so to speak, throw away the ladder after he has
climbed up it.)"

(6.54 of Wittgenstein�s Tractatus.)
From: Nils Goesche
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <lky97uv67l.fsf@cartan.de>
····@vanderbilt.edu (sv0f) writes:

> In article <··············@darkstar.cartan>, Nils Goesche <···@cartan.de> wrote:
> 
> >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.
> 
> "My propositions serve as elucidations in the following way: anyone
> who understand me eventually recognizes them as nonsensical, when he
> has used them � as steps � to climb beyond them. (He must, so to
> speak, throw away the ladder after he has climbed up it.)"
> 
> (6.54 of Wittgenstein�s Tractatus.)

Yes, I was thinking of exactly that paragraph :-) The tractatus makes
for a lot of nice quotes -- but unfortunately I don't own an English
translation.  I think I'll go to Amazon right now...

Regards,
-- 
Nils G�sche
"Don't ask for whom the <CTRL-G> tolls."

PGP key ID 0x0655CFA0
From: JP Massar
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <3dd5885a.9722244@netnews.attbi.com>
On Thu, 14 Nov 2002 17:40:44 -0800, ···@jpl.nasa.gov (Erann Gat)
wrote:

>In article <····························@posting.google.com>,
>·········@gmx.net (thelifter) wrote:
>
>> 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.
>
 
Maybe you should quote the White Knight and be done with it.

:-)
From: Matthew Danish
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <20021114233311.C19796@lain.cheme.cmu.edu>
On Thu, Nov 14, 2002 at 04:37:16PM -0800, thelifter wrote:
> 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.

> [...]
> 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.

-- 
; Matthew Danish <·······@andrew.cmu.edu>
; 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."
From: Erik Naggum
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <3246309873649099@naggum.no>
* ·········@gmx.net (thelifter)
| 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.
From: Erann Gat
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <gat-1411021721020001@k-137-79-50-101.jpl.nasa.gov>
In article <················@naggum.no>, Erik Naggum <····@naggum.no> wrote:

>   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.
From: Erik Naggum
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <3246317730436450@naggum.no>
* 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.
From: Erann Gat
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <gat-1411022354240001@192.168.1.51>
In article <················@naggum.no>, Erik Naggum <····@naggum.no> wrote:

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

My guide is for people who understand and appreciate the difference
between a reference and a tutorial.  At the risk of stating the painfully
obvious, my writing of "The Idiot's Guide..." should in no way be
construed as my advocating against reading the standard, or any other
work.

And another thing:

"A 'critic' is a man who creates nothing and thereby feels qualified to
judge the work of creative men. There is a logic in this; he is unbiased -
he hates all creative people equally. "

       -- Robert Heinlein

My guide, flawed as it may, has one siginficant advantage over yours: mine
exists.

E.
From: Erik Naggum
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <3246379133344133@naggum.no>
* Erann Gat
| My guide is for people who understand and appreciate the difference
| between a reference and a tutorial.

  You contradict yourself, or you try one of your annoying backhand insults,
  again.  Please try to stay on topic and be constructive.  Getting approval
  from me should not be your primary purpose, and hence lack thereof should
  not cause you to fight for it, which is extremely unlikely to produce it.

| And another thing:
| 
| "A 'critic' is a man who creates nothing and thereby feels qualified to
| judge the work of creative men. There is a logic in this; he is unbiased -
| he hates all creative people equally. "
| 
|        -- Robert Heinlein

  Poor little Erann.  So hurt.  So unable to think, for what does that quote
  say about a person who calls another person a critic when he is not?

| My guide, flawed as it may, has one siginficant advantage over yours: mine
| exists.

  You amaze me, Erann.  So hateful, so destructive, so emotional, so blind.
  I have suggested people actually go read books on Common Lisp, such as
  CLtL and CLtL2, and also the standard.  In a pathetic display of your
  emotional dysfunction, you now argue that these books and the standard do
  not /exist/?  What kind of idiocy is that?  What do you gain by hammering
  on what you perceive as your critics when all you should do was to make
  your own work better?  Wasting time on attacking me means that your whole
  purpose is /not/ to explain special variables, but to have people approve
  of you as a person.  That is extremely unlikely to happen when you act the
  way you have chosen now.  So get back to the text and get it right, and
  you may have a chance of such approval.

  Normally, with a title like the one you have chosen, the intention is to
  make the audience to feel at ease when they are mortally afraid of experts
  -- it is not intended to describe the author.  You may wish to make the
  former intention clearer.

-- 
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.
From: Erann Gat
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <gat-1511021421440001@k-137-79-50-101.jpl.nasa.gov>
In article <················@naggum.no>, Erik Naggum <····@naggum.no> wrote:

>   Poor little Erann.  So hurt.  So unable to think, for what does that quote
>   say about a person who calls another person a critic when he is not?

Your comment about my guide not being "for people who seek to understand"
sounded like criticism to me.  (In fact, it sounded like more than
criticism.  It sounded like an insult.)

> | My guide, flawed as it may, has one siginficant advantage over yours: mine
> | exists.
> 
>   You amaze me, Erann.  So hateful, so destructive, so emotional, so blind.
>   I have suggested people actually go read books on Common Lisp, such as
>   CLtL and CLtL2, and also the standard.  In a pathetic display of your
>   emotional dysfunction, you now argue that these books and the standard do
>   not /exist/?  What kind of idiocy is that?

Obviously I did not mean to claim that CLTLN and the standard don't
exist.  What I meant (again at the risk of stating the painfully obvious)
was that you didn't write them.

>  What do you gain by hammering
>   on what you perceive as your critics when all you should do was to make
>   your own work better?

I would like very much to improve the Guide, but I find absolutely nothing
in anything you've written that's going to (or even intended to) help me
do that.

>   Normally, with a title like the one you have chosen, the intention is to
>   make the audience to feel at ease when they are mortally afraid of experts
>   -- it is not intended to describe the author.  You may wish to make the
>   former intention clearer.

Actually, the title is intentionally ambiguous on that point, an attempt
at self-deprecating humor.  This has been the case since the first edition
of the guide, where I made this explicit.  See

http://groups.google.com/groups?selm=gat-0203001548330001%40milo.jpl.nasa.gov

E.
From: Erik Naggum
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <3246396714296203@naggum.no>
* Erann Gat
| Your comment about my guide not being "for people who seek to understand"
| sounded like criticism to me.  (In fact, it sounded like more than
| criticism.  It sounded like an insult.)

  And since it sounded like that to you, you take it upon yourself to
  revenge it, is that it?  Some primitive cultures, notably in the Middle
  East, have a concept of "honor" that makes it impossible to say anything
  to them that could conceivably cause them to lose their fragile self-image
  of their honor.  I have no intention whatsoever of catering to primitive
  cultures, wherever they may have been exported or imported or whoever
  suffers from their anti-intellectual notions that turn a statement of
  fact into an insult that turns these rabidly irrational people into hate
  machines that believe they revenge an attack that was never there, and
  therefore prevent them from understanding that they in fact attack first
  and thus do not even grasp that their openly hostile acts are unfair and
  provide legitimate reason for rebuttal and rejection, if not defense.

| Obviously I did not mean to claim that CLTLN and the standard don't
| exist.  What I meant (again at the risk of stating the painfully obvious)
| was that you didn't write them.

  The relevance of which being ...?  This is so stupid a line of argument
  that you should be happy that I do not call you on it further.  Drop it.

| I would like very much to improve the Guide, but I find absolutely
| nothing in anything you've written that's going to (or even intended to)
| help me do that.

  I think it would be improved by being removed.  I think you would be
  improved by being removed, too, since you are such an annoying, hostile
  person who never seem to be able to read anything I write without seeing
  an insult that you have to attack me for.  Realize that your perception
  of what I write is mainly in your own head.  You should have learned by
  now that because you feel a certain way does not mean that there was any
  intention to make you feel that way.  Some people here on c.l.l seize any
  and all opportunity to be insulted and therefore attack me regardless of
  what I actually say, and you are one of them.  You are broken, Erann Gat.
  Repair yourself and stop inflicting your malfunction on me.  Thank you.

-- 
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.
From: Erann Gat
Subject: Re: Idiot's guide to special variables take 2
Date: 
Message-ID: <gat-1511021711270001@k-137-79-50-101.jpl.nasa.gov>
In article <················@naggum.no>, Erik Naggum <····@naggum.no> wrote:

> | Obviously I did not mean to claim that CLTLN and the standard don't
> | exist.  What I meant (again at the risk of stating the painfully obvious)
> | was that you didn't write them.
> 
>   The relevance of which being ...?

Good grief, are you really that daft?  The relevance of which being that I
wrote a tutorial and you didn't.  So either you think tutorials have no
value, in which case we'll have to agree to disagree on that.  Or you do,
in which case I respond to your non-constructive criticism of my tutorial
by simply saying once again that, bad as it is, it's better than yours.

>   I think it would be improved by being removed.

Your opinion is noted.  Now buzz off.

E.