* (let ((x 1)) (eval 'x))
In: LET ((X 1))
(LET ((X 1))
(EVAL 'X))
Warning: Variable X defined but never used.
Error in KERNEL::UNBOUND-SYMBOL-ERROR-HANDLER: the variable X is unbound.
Restarts:
0: [ABORT] Return to Top-Level.
Debug (type H for help)
(EVAL X)
0]
This seems counterintuitive to me. Is EVAL just using the global
environment? Is that what the language spec says it should be? If
that is the case, how could the following behaviour be explained:
* (defvar x 100)
X
* (let ((x 1)) (eval 'x))
1
* x
100
*
Note that the eval only seems to work after a *GLOBAL* variable 'x'
has been defined. I consider this very strange, but it seems very
improbable that the authors of these implementations would overlook
such an obvious bug. So, what's the explanation?
--
Malcolm Chan (English), Zeng Qiangyong (Chinese) _/ _/ _/_/_/
Student, Computer Science Department _/_/ _/_/ _/
University of Auckland _/ _/ _/ _/
EMail Address: mal...@kcbbs.gen.nz _/ _/ _/_/_/
This seems counterintuitive to me. Is EVAL just using the global
environment? Is that what the language spec says it should be?
Not exactly, it is using the null lexical environment and the current
dynamic environment.
Espen Vestre
http://www.harlequin.com/books/HyperSpec/Body/fun_eval.html
Malcolm then asks about (let ((x 1)) (eval 'x)) after (defvar x 100). as
the above web page will tell you, `eval' "evaluates the form in the current
dynamic environment and the null lexical environment". `defvar' makes the
variable dynamic. `let'-bindings on dynamic variables do not make them
lexical.
hope this helps.
#\Erik
Hmm.. you're right of course, but it does sort of feel counterintuitive.
Anyone got any *good* reasons why it is this way? Efficiency reasons,
(ancient) history, or something? Or am I missing some obvious
functional reason?
----------------------------------------------------------
Tim Chippington Derrick | My ideas, comments, views etc,
der...@ilog.co.uk | Not necessarily anyone else's
ILOG UK Ltd | ... but I hope so
Tim also says that it "does sort of feel counterintuitive". I have had
many occasions to upgrade my intuition when working with Lisp. once, I
comforted a friend who was very frustrated with `eval-when', and said that
it becomes intuitive only when it has ceased to be an impenetrable mystery.
#\Erik
> * (let ((x 1)) (eval 'x))
> Warning: Variable X defined but never used.
> Error in KERNEL::UNBOUND-SYMBOL-ERROR-HANDLER: the variable X
> is unbound.
>
> This seems counterintuitive to me. Is EVAL just using the global
> environment? Is that what the language spec says it should be?
Yes, and yes. It's a result of the fact that Common Lisp variables
use lexical scoping by default. Lexical scoping means you can't
access the value of a binding from anywhere except inside the scope
of that binding. The rule applies to every function, not just EVAL:
? (defun foo () x)
;Compiler warnings :
; Undeclared free variable X, in FOO.
FOO
? (let ((x 1)) (foo))
;Compiler warnings :
; Unused lexical variable X, in an anonymous lambda form.
> Error: Unbound variable: X
> While executing: FOO
If you really need to get the value of X from inside FOO, you can
make FOO a macro. This works because the compiler actually places
the macro's code inside of the LET form, rather than just calling
the code from inside the LET form:
? (defmacro foo () 'x)
FOO
? (let ((x 1)) (foo))
1
Lexical scoping is important, not only for making compilers efficient
but also for certain kinds of reasoning about programs. For example,
consider the following simple version of MAPCAR:
(defun mapper (f l)
(do ((in l (rest in))
(out nil (cons (funcall f (first in)) out)))
((endp in) (nreverse out))))
Note that it uses the destructive (and normally dangerous) function
NREVERSE on the value of OUT. This can be done with absolute
safety, because the binding of OUT is lexical and therefore the
function F can't access OUT, not even if F makes use of EVAL.
> If that is the case, how could the following behaviour be explained:
>
> * (defvar x 100)
> X
> * (let ((x 1)) (eval 'x))
> 1
>
> Note that the eval only seems to work after a *GLOBAL* variable 'x'
> has been defined.
DEFVAR doesn't just define a global variable X; it also declares
that all variables X are "special." A special variable is dynamic
rather than lexical, so it bypasses the normal scoping rule. Look
what would happen if you used SETQ rather than DEFVAR, to establish
a global variable without declaring it to be special:
? (setq x 100)
100
? (let ((x 1)) (eval 'x))
;Compiler warnings :
; Unused lexical variable X, in an anonymous lambda form.
100
-- Robert
http://www.harlequin.com/books/HyperSpec/Body/sec_3-1-1.html
#\Erik
Erik Naggum wrote (15-Aug-96 13:00:12):
>http://www.harlequin.com/books/HyperSpec/Body/fun_eval.html
When I saw Malcom's post, I rushed to clisp to try it out, and he was
right! It was the most weird thing I've ever seen concerning LISP. Is it a
bug? (same bug on all implementations?) After reading the post I've quoted,
I thing I've understand it.
First of all, I'd like to ask anyone to explain what are those dynamic
and lexical enviroments. The idea that I have is that the lexical enviroment
includes local variables created by "let" and lambda variables.
In this perspective I understand that a (let ((x 1)) ...) does some
sort of a local (setf x 1). If x already exists, it just sets it, otherwise it
creates the variable. However this is somehow wrong, since
(setf y 123)
(let ((y 1)) (eval 'y))
returns 123 instead of 1. Therefore there must be a difference between x and
y. This is confirmed by a (describe 'x) that returns
This is the symbol X, a variable declared SPECIAL.
and a (describe 'y) returns
This is the symbol Y, a variable.
I suppose that these different variable status is the key to the problem. Yet
I don't like to see exceptions in a apparently "clean" language as LISP was
supposed to be. In a general way, I guess that any exception to a rule is
dangerous.
Regards,
--
+--------------------------------------------------------+-----------+
| Rodrigo Ventura, alias <Master Yoda> | / |
+--------------------------------------------------------+ - / --- |
| Electronic Engineering Course, Control and Robotics | | | | |
| Instituto Superior Técnico, Lisboa, Portugal | | | | |
+--------------------------------------------------------+ - / | |
| L36...@alfa.ist.utl.pt, http://alfa.ist.utl.pt/~l36612 | / |
+--------------------------------------------------------+-----------+
The HyperSpec says that "variable" just means "variable binding."
Using that definition:
In article <4v7ifq$9...@Mars.mcs.com>, I wrote:
>1> DEFVAR doesn't just define a global variable X; it also declares
>2> that all variables X are "special." A special variable is dynamic
>3> rather than lexical, so it bypasses the normal scoping rule. Look
>4> what would happen if you used SETQ rather than DEFVAR, to establish
>5> a global variable without declaring it to be special:
>6>
>7> ? (setq x 100)
>8> 100
>9> ? (let ((x 1)) (eval 'x))
>A> ;Compiler warnings :
>B> ; Unused lexical variable X, in an anonymous lambda form.
>C> 100
OK, in line 5 change "it" to "its name" or "X." Then it's correct.
In article <30493952...@arcana.naggum.no>,
OK, still using the HyperSpec definition: what you say above is
correct, as far as it goes, but it does not invalidate the point
I was trying to make. It is possible for a program to have a
lexical variable and a dynamic variable both of which have the same
name. Establishing a dynamic variable named X does not preclude
the existence of a lexical variable named X.
The point I was making for Mr. Chan is that DEFVAR has two different
side effects: (A) it assigns a global value to a name, and (B) it
also declares that all uses of that name will be dynamic. Mr. Chan
observed an effect that DEFVAR had on his code, which he thought
was due to A; I was explaining that it was really due to B.
Having said all that, I should point out that the HyperSpec's
definition of "variable" as meaning "variable binding" is not
exactly standard. It doesn't mesh well with the following from
CLtL2 section 5.1.2:
The value a special variable has when there are currently no
bindings of that variable is called the global value of the
(special) variable. A global value can be given to a variable
only by assignment, because a value given by binding is by
definition not global.
Thus using CLtL2 terminology, the following code:
(defvar x 3)
(+ x x)
does not involve any bindings. So if (as defined by the HyperSpec)
a variable is just a variable binding, then the code above does
not involve any variables!
I don't blame the authors of the HyperSpec for this; I'm not sure
it's even possible to come up with consistent definitions that
don't conflict with CLtL2.
While I'm on the subject, here is something else I don't like about
the HyperSpec definition of "variable:"
(terpri *query-io*)
I don't like to say that the above code refers to different variables
at different times, depending on whether *query-io* has been rebound.
I would rather say that it refers to the same variable every time
it is called, but not necessarily to the same binding. I can't
say this if "variable" and "variable binding" are the same thing.
I suppose if I want to say that and be consistent, I will probably
end up having to espouse the following definition of "variable:"
* Each individual lexical binding is an individual variable.
* All dynamic bindings which share the same name, along with
the global value assigned to that name, together refer to a
single dynamic variable.
In other words, a program can have many lexical variables named X
but only one dynamic variable named X.
But given all the confusion, perhaps it would be better just not
to use the word "variable" without qualifying it, e. g. "variable
name," "variable binding," "variable reference," etc.
Well, there it is. Sorry it got so long. I guess I got dragged
into something much bigger and more involved than what I expected
when I first replied to Mr. Chan.
Comments, anyone?
-- Robert
I don't think there is anything I can do to help Robert with the confusion
over environments, since he seems to ignore what I have already said, so
I'll leave it at that.
#\Erik
--
life is hard and then you post.
You're confused because the word "binding" is used in a number of different
ways in CLtL and the Common Lisp spec.
As a noun, "binding" means any association between a name and its value.
As a verb, "to bind" usually refers to establishing a *local* binding.
Thus, (defvar x 3) creates a binding, but we don't say that the value was
given "by binding". (let ((x 3)) ...) gives the variable a value by
binding.
]I don't blame the authors of the HyperSpec for this; I'm not sure
]it's even possible to come up with consistent definitions that
]don't conflict with CLtL2.
The HyperSpec makes no attempt to be consistent with CLtL2. The HyperSpec
contains the text of the ANSI specification.
]While I'm on the subject, here is something else I don't like about
]the HyperSpec definition of "variable:"
]
] (terpri *query-io*)
]
]I don't like to say that the above code refers to different variables
]at different times, depending on whether *query-io* has been rebound.
]I would rather say that it refers to the same variable every time
]it is called, but not necessarily to the same binding. I can't
]say this if "variable" and "variable binding" are the same thing.
]
]I suppose if I want to say that and be consistent, I will probably
]end up having to espouse the following definition of "variable:"
]
] * Each individual lexical binding is an individual variable.
] * All dynamic bindings which share the same name, along with
] the global value assigned to that name, together refer to a
] single dynamic variable.
If we were defining the terms using more formal, computer science terms, we
would say that a binding refers to the association between a name and a
location where a value can be stored. When a local binding is established,
a new association is created.
One of the reasons CL doesn't use that terminology is because it only
applies to variable bindings. The term "binding" is also used in CL in
reference to functions, blocks, GO-tags, CATCH-tags, etc.; in these cases,
the target of a binding is not a storage location but some abstract
programming construct. Also, mentioning storage locations suggests
implementation specifics that we didn't want to get into.
--
Barry Margolin
BBN Planet, Cambridge, MA
bar...@bbnplanet.com - Phone (617) 873-3126 - Fax (617) 873-6351
(BBN customers, please call (800) 632-7638 option 1 for support)
http://www.harlequin.com/books/HyperSpec/Body/sec_3-1-1.html
this section contains what you should need to know about environments.
I wasn't confused about the distinction between noun and verb.
I hope this doesn't sound petulant, but... Please re-read your
article carefully. The word "bindings" in the second line of the
excerpt from CLtL2 is clearly a noun. I was not confused about
any of this [*]; I was merely pointing out a small disagreement
between CLtL2 and the HyperSpec.
[*] Actually I might be confused about the authorship of the
HyperSpec. It is not clear to me exactly how much difference there
is between the HyperSpec and the ANSI standard. The HyperSpec
itself only claims that it is "derived from" the ANSI document, so
I thought it might include some original material not from ANSI
(just as Franz Inc.'s CLtR was "derived from" CLtL, but included
original material authored by Franz).
At any rate, I regret having implied that CLtL2 is somehow "more
standard" than the HyperSpec. I hereby make the following correction
to my article of 8/19/96: replace the words "exactly standard" with
the words "consistent with CLtL2."
> Thus, (defvar x 3) creates a binding, but we don't say that the
> value was given "by binding". (let ((x 3)) ...) gives the variable
> a value by binding.
According to the above excerpt from CLtL2, (defvar x 3) does NOT
create a binding. Your use of "binding" is fine with me, in fact
I like it better than the one in CLtL2. I was just pointing out
that it is not consistent with the usage in CLtL2.
> The HyperSpec makes no attempt to be consistent with CLtL2.
Now you have hit the nail on the head: I think this is the root of
all the confusion. I wasn't saying this inconsistency is bad or
even unnecessary -- I was just saying that it's hard to get everyone
using the exact same definitions for certain words. I think that's
probably the reason that Erik and I are having such difficulty
understanding each other. It's not surprising that the two of us
have trouble communicating, since even CLtL2 and the HyperSpec
can't agree with each other on the exact meanings of these words.
-- Robert
> Robert Munyer offers the following pearl for our enjoyment: "I
> should point out that the HyperSpec's definition of "variable"
> as meaning "variable binding" is not exactly standard." matter
> of fact is: it _is_ exactly standard. the HyperSpec contains
> the text from ANSI X3.226-1994.
The HyperSpec states merely that it is "derived from" the standard.
In fact, here is a quote from the HyperSpec:
"The Common Lisp HyperSpec is not the ANSI Common Lisp standard"
When I noticed that the HyperSpec was inconsistent with CLtL2, I
thought it would be a good idea to attribute the inconsistency to
the document where I actually saw it, rather than to the document
from which it was "derived."
I haven't seen the non-HyperSpec version of the ANSI document, but
I will take your word for it that the definition of variable is
the same in both. So, OK, I will use that definition. And I regret
having implied that CLtL2 is somehow "more standard" than the
HyperSpec. I hereby make the following correction to my article
of 8/19/96: replace the words "exactly standard" with the words
"consistent with CLtL2."
> I don't think there is anything I can do to help Robert with the
> confusion over environments, since he seems to ignore what I have
> already said, so I'll leave it at that.
Wait a minute. Now it sounds like you think there is something
wrong with my 8/19 explanation of variables and scoping. This
whole mess started when you misunderstood what I wrote on 8/18,
while I was innocently trying to help Mr. Chan understand his
problems with EVAL. On 8/18 I probably should have written "its
name" instead of "it" so that you would not have been able to
misunderstand. But I was very careful not to leave room for that
kind of misunderstanding in the 8/19 article. I believe that one
was 100% correct, except for the words "exactly standard" which
have nothing to do with the part that explains variables and scoping.
If you think I said something wrong, please tell me what it is;
don't just hint that I am wrong by saying that I "seem to ignore"
you. I haven't ignored anything you have said. If there is
something I don't understand, I want to be corrected. But you
haven't corrected me or supplied any specific details; you have
only posted a vague hint that I am wrong. Hints won't do me (or
anyone else) any good.
You seem to have in mind a specific misconception under which you
think I am laboring. If so, please state this misconception
explicitly -- or better yet, post a snippet of code that you think
I will interpret incorrectly.
Just to make this absolutely explicit: I believe my articles of
8/18 and 8/19 were 100% correct if you make the following changes:
* 8/18: change "it" to "its name."
* 8/19: change "exactly standard" to "consistent with CLtL2."
I don't think you have said anything that conflicts with this
belief. If you (or anyone else) disagree, please tell me why.
-- Robert
LISP is a language family, not a language. It accomodates many points
of view, even those that are mutually exclusive, by allowing different
dialects which permit and rule out various things. Beware of speaking
overbroadly about what "it" is, or of inferring what any dialect's
goals were without doing a historical search to find that out.
DEFVAR proclaims a name SPECIAL. When proclaimed SPECIAL, the effect
is pervasive (affects bindings of that name). Some of the reason for
Common Lisp's semantics are historical, having allowed for the
evolution of the language and some of its large programs from a time
when there was no lexical binding at all.
Common Lisp is a commercially powerful dialect--its goal is to work
reliably, predictably, and usefully. It does these things. Aesthetics
are important to the CL community, but they are formally (as a matter of
design principle) secondary/subordinate to practicalities such as cost
of change of existing compilers or user programs.
That Common Lisp is sometimes messy at the edges is a sign of the fact
that people have used it enough to care that their programs not be
broken over time. The design of Common Lisp was done with the
assumption that there were people in the community who used the
language it referred to and who would want to continue throughout the
long process to be using that language without undue economic
hardship. Even small changes to a language can mean many $10K's of
real dollar cost to a company to hire a consultant to fix old code, and
we tried in our work to be mindful of this.
Indeed, languages that can freely tolerate arbitrary changes for the
sake of being "elegant" or "clean", no matter how many (or how few)
users are affected will have trouble attracting a certain commercial
community to rely on them as a stable base for building programs that
will last into the future. (They may indeed find OTHER commercial
communities that prefer aesthetics and tolerate breakage that occurs
toward that end, but that is not a disproof of my claim that not ALL
companies want aesthetics over all else.)
Professional CL programmers will tell you that good style is to ALWAYS
put *'s around the name of a variable you will proclaim SPECIAL
(whether explicitly or through DEFVAR or DEFPARAMETER). In that way,
you will always be reminded when binding it that you are going to get
a SPECIAL, and you effectively (though not formally) get a separate
namespace.
You might ask why not just make it a separate namespace. The answer is
in the history...
First, consider the printer control variables *PRINT-LENGTH* and
*PRINT-LEVEL*. It would be quite cumbersome in practice to have to
bind them by
(LET ((*PRINT-LENGTH* 3) (*PRINT-LEVEL* 3))
(DECLARE (SPECIAL *PRINT-LENGTH* *PRINT-LEVEL*))
...)
to have the binding "take the obvious effect". Program errors would
just about always be indicated if someone just wrote
(LET ((*PRINT-LENGTH* 3) (*PRINT-LEVEL* 3))
...)
and if the semantics were not to produce a special binding automatically.
Yes, it's true, we could have made a DYNAMIC-BIND form like EuLisp later
did. One reason, for better or worse, that we did not is that it made
the transition from older dialects of Lisp more difficult. It used to be
in some older dialects that all variables were defaultly SPECIAL.
That brings me to my second example. Many people bridged the gap by
adding a few PROCLAIM's at the front of their program and then writing
"the old way".
(PROCLAIM '(SPECIAL A B C D))
(DEFUN FOO (A B C D) ...)
Then, one-by-one as they could prove that A,B,C, and/or D was not
needed to be special because they'd fully tracked the data flow and
seen that no special references were still being made, they could
simply remove the SPECIAL proclamation for that one ... until one day
their program ran with no special proclamations. If instead CL had
REQUIRED a new form, like DYNAMIC-BIND, to do special binding,
it would have meant all such forms would have been rewritten AND
re-shaped, as in:
(DEFUN FOO (A0 B0 C0 D0)
(DYNAMIC-BIND ((A A0) (B B0) (C C0) (D D0))
...))
This would have made code hard to read including even simpler things
like pushing things farther and farther to what might have been an
already cramped right margin in the editor (a practical consideration
we've all struggled with in the Lisp community). Also you'd have had
to do something even more complicated to have transitioned old code
that did
(PROCLAIM '(SPECIAL A B))
(DEFUN FOO (A &OPTIONAL (B (F))) ...)
where (F) might have referred to the SPECIAL variable A, and where:
(DEFUN FOO (A0 &OPTIONAL (B0 (F)))
(DYNAMIC-BIND ((A A0) (B B0))
...))
was NOT a correct rewrite because (F) would happen before A was bound
as a dynamic variable and since F might refer specially to A, you
needed to arrange for the A to be bound before F was called. To
correctly rewrite such a function using DYNAMIC-BIND would have
required:
(DEFUN FOO (&REST ARGS)
(LET ((N-ARGS (LENGTH ARGS)))
(UNLESS (OR (= N-ARGS 1) (= N-ARGS 2)) (ERROR ...))
(DYNAMIC-BIND ((A (POP ARGS)))
(DYNAMIC-BIND ((B (IF (= N-ARGS 2) (CAR ARGS) (F))))
....))))
Like it or not, this degree of reshaping would not have supported the
smooth transition of old programs into the future at the time lexical
scoping (an undeniably good idea we had to implement, in spite of the
cost) was introduced. So CL adopted the convention of allowing one to
individually declare variables locally or globally in various ways that
supported the transition we were undergoing.
Of course, the real power of CL is that if you don't like what it
gives you, you can pretty much make your own way of doing things. e.g.,
(DEFMACRO DYNAMIC-BIND (VARS-AND-BINDINGS &BODY FORMS)
`(LET ,VARS-AND-BINDINGS
(DECLARE (SPECIAL ,@(MAPCAR #'CAR VARS-AND-BINDINGS)))
,@FORMS))
(DEFMACRO DYNAMIC (NAME)
`(LOCALLY (DECLARE (SPECIAL ,NAME)) ,NAME))
and then just always use DYNAMIC-BIND to bind specials and DYNAMIC to
reference them.
If you do this, then you won't get any surprising effects with EVAL
because only the things you dynamic-bound will be visible to EVAL.
Or if you use the standard convention of putting *'s around special
variable names, you won't get surprising effects either. No experienced CL
programmer is surprised by
(LET ((*PRINT-LEVEL* 3)) (EVAL '*PRINT-LEVEL*)) => 3
because they know this is a dynamic binding. They ARE surprised by
(LET ((X 3)) (EVAL 'X)) => 3
but not because of what EVAL does. They will immediately scream
"You proclaimed X special? You're going to lose really badly."
note that CLtL2 was not an official document; CLtL1 was; ANSI X3.226-1994
Common Lisp is. the HyperSpec at Harlequin is Kent Pitman's formatting
into HTML from the exact same source text that went into the final text of
the standard that was later published by ANSI. Kent Pitman was the editor
of the standard. see the Credits section in the standard or the HyperSpec.
let's leave this much ado about nothing to the lawyers should the need to
compare the HyperSpec to the Real Paper Thing come up. (part of) Robert's
answer was wrong, relied on implementation specifics at best, and is no
better off after his attempted rescue missions. end of story.
>I hope this doesn't sound petulant, but... Please re-read your
>article carefully. The word "bindings" in the second line of the
>excerpt from CLtL2 is clearly a noun. I was not confused about
>any of this [*]; I was merely pointing out a small disagreement
>between CLtL2 and the HyperSpec.
Sorry, I was looking at the phrase "by binding" in the 4th line (this use
of the word is a "verbal" which is a cross between a noun and a verb), and
didn't see the other use in the 2nd line.
Basically, the problem is that CLtL (and, to a lesser extent, the ANSI spec
(and by derivation, the HyperSpec)) is not very careful about the use of
the word "binding". Sometimes it means "any kind of binding", while other
times it implicitly means "local binding". It's usually pretty obvious
when it means the latter; in the above paragraph, the fact that it's
describing the difference between global and local values, it's obvious
that "binding" means "local binding".
In article <30495769...@arcana.naggum.no>,
Erik Naggum <er...@naggum.no> wrote:
> Robert Munyer seems to want to maintain that CLtL2 is his authority
> in the presence of ANSI Common Lisp
When I first saw the HyperSpec, for about one day I thought its
definition of variable was "not exactly standard." I thought this
because: (a) the HyperSpec claims not to be the standard; (b) the
definition conflicts with CLtL2; and (c) I had not heard that the
ANSI standard redefined any basic terminology versus CLtL2.
Because of this I carelessly implied that the HyperSpec definition
was somehow less standard than the one used by CLtL2. People kindly
corrected me and I retracted that statement about 26 hours after
I posted it. You posted your snide and disingenuous reply AFTER
my retraction.
> arguments to the effect that people write their own stuff into
> standards documents are specious at best. I cannot think of
> anybody who would actually do that --
Take a look at "Common Lisp, the Reference" some time, and you will
see what I was talking about. It has nothing to do with "writing
stuff into" standards documents.
> it would be so easy to prove that tampering had taken place and
> the credibility of whever did it would be destroyed right there.
Nobody here has said anything about tampering (except you). Adding
your own material is not tampering, when you explicitly state that
the resulting document is not the standard.
> note that CLtL2 was not an official document; CLtL1 was;
The paragraph I quoted from CLtL2 also appeared in CLtL1.
We might as well stop talking about this, because it really has
nothing to do with the subject of this thread. The only reason I
brought up the authorship of the HyperSpec was to discuss the
meaning of the word "variable," and the only reason I brought up
the meaning of the word "variable" was that I thought the difference
in definitions might be the reason for your complaint about my
original article. But it turns out that that was NOT the reason,
because you replied that I was ignoring you. Therefore discussion
of the meaning of "variable" is just a useless side issue, and
discussion of the authorship of the HyperSpec is just a side issue
on a side issue. So let's get back to the main issue, now that
I've found that the meaning of "variable" has nothing to do with
your complaint.
> (part of) Robert's answer was wrong, relied on implementation
> specifics at best, and is no better off after his attempted rescue
> missions. end of story.
Wait a minute. STOP DOING THAT! It is rude and offensive. You
keep saying that part of my answer was wrong somehow, without
specifying how. Every time I challenge you to be specific you just
post another article saying (or implying) that I made some vague,
unspecified error. That is not a reasonable way to debate. In
Usenet you are not supposed to simply state that someone is wrong;
you are supposed to explain WHY he or she is wrong so that everyone
can benefit.
A pattern seems to be emerging here. Every time I try to get you
to be more specific, you become even more vague. On 8/18 I posted
an article to explain scoping to Mr. Chan; you jumped in and said
I was wrong, and mentioned a URL to a HyperSpec page that does not
conflict with what I wrote. On 8/19 I tried to find out if your
unspecified complaint had something to do with the definition of
"variable;" you replied with a vague comment that I was "confused
about environments" and "ignoring what you already said." On 8/20
I challenged you to (finally) make your point, with a specific
complaint or better yet code snippets. You replied with the
amazingly evasive comment above: "(part of) Robert's answer was
wrong..." How much more vague could you possibly get?
A pattern of increasing evasiveness is a sign of a person who
doesn't have the slightest idea what he is talking about. I hate
to say anything insulting like that, but you forced me into it.
If you don't want me to say things like that about you, then just
quit evading and (at long last) make your point.
Please, respond to the challenge at the bottom of my 8/20 article.
Do not simply evade it as you did on 8/21.
Or better yet, I will put a new challenge below. Please respond
to this one. If you ignore both challenges again, and reply as
you did before, that will make two cycles in a row in which you
have refused to answer my questions. If you do this I will have
to assume that you have some ulterior motive for refusing to answer.
I know it's not nice to say that about someone, but how else could
I explain your refusal?
Below I will give you a DAG of numbered statements, all of them
explaining a difference between SETQ and DEFVAR. Most of these
statements include "pointers" to other statements, from which I
claim they follow necessarily. For each of these statements, please
tell us whether you agree or disagree. If you choose to dispute
some statement N but not to dispute statement M from which I claim
N follows, then you must dispute my claim that N follows from M.
And you must dispute statements #1 and #2, if you wish to justify
your articles of 8/18 and 8/19 respectively.
Statement #1 is my original statement, to which you objected. I
claim it is technically correct, but it is not as well phrased or
as meaningful as I would have liked, because I was being a little
careless in my use of the words "variable" and "it." After all,
I was just explaining EVAL and scoping to a beginner. A more
reasonable reader probably would have understood what I meant by
reading the code snippet.
Statement #2 is my original statement after I corrected it on 8/19.
(Apparently you still object to it in this corrected form, because
on 8/19 you said I was ignoring what you said on 8/18, and on 8/21
you said my "rescue missions" were unsuccessful.)
I have prepared this DAG in excruciating detail, with very fine
grain, because I am trying very hard to get your complaint narrowed
down to something that is explicit enough to be worth discussing.
1. Look what would happen if you used SETQ rather than DEFVAR, to
establish a global variable without declaring it to be special:
[In the context of my original article, and using my old
(informal and outdated) definition of "variable," my intention
was for statement #1 to follow from #2 or #3. Using the
standard definition of "variable" (on which we now all agree),
#1 is still technically correct because it follows from #6.
The binding created by statement #1 is special, but it's not
special by declaration; it's special simply by lack of an
enclosing lexical binding. Yes, I know I'm being a bit of
a Philadelphia lawyer here, but you forced me into it. And
remember, to justify the abusive articles you have posted,
you must dispute statement #2 below as well as #1.]
2. Look what would happen if you used SETQ rather than DEFVAR, to
establish a global variable without declaring its name to be
special: [in the context of my original article, this statement
follows from statement #3].
3. When you use SETQ at the top level on a previously unused variable
name, you are not declaring that variable name to be special.
[this follows from statement #4 or #5].
4. When you use SETQ at the top level on a previously unused variable
name, you are not declaring that variable name to be special,
and you will be able to use that name for lexical variables.
5. When you use SETQ on a variable name, you are not declaring that
variable name to be special. [this follows from statement #6].
6. When you use SETQ on a variable name, you are not declaring
anything to be special. [this follows from statement #7].
7. When you use SETQ on a variable name, you are not declaring
anything at all. [this follows from statement #8].
8. When you use SETQ you are not making a declaration. Unlike
DEFVAR, SETQ does not include an implicit PROCLAIM.
2---3---4
\
5---6---7---8
/
1
[ Yes folks, I know this is a ridiculous level of detail. But I
can't think of any other way to narrow down the complaint and
finally get an answer out of this guy. ]
This article is a final attempt to get you to say something useful.
If you brush this one off too, I will just have to assume that you
are a "flame baiter" who likes to start arguments but is not
interested in serious discussion.
-- Robert
P. S. Of course, others are welcome to contribute. I know there
are plenty of geniuses who read this newsgroup. If I have really
made a mistake in this chain of reasoning, perhaps one of you will
step forward and explain where and why. I promise I won't flame
you, and even graciously accept being wrong, if you will just be
reasonably explicit rather than saying something like "duh, part
of it is wrong." As I said before, snippets of code which demonstrate
your point are especially welcome.
Now that I've gone to the trouble of writing all this, I realize
it's probably just a big waste of time. I'm posting it anyway,
just in case someone might find something useful in it. After all,
this isn't exactly a high-traffic newsgroup. But I've learned my
lesson: next time a flame baiter attacks, I'll try to ignore him.
I have one small comment to add:
In article <KMP.96Au...@romulus.harlqn.co.uk>,
Kent Pitman <k...@harlqn.co.uk> wrote:
> Indeed, languages that can freely tolerate arbitrary changes for
> the sake of being "elegant" or "clean", no matter how many (or
> how few) users are affected will have trouble attracting a certain
> commercial community to rely on them as a stable base for building
> programs that will last into the future.
That's why it's great that we have Scheme as well as Common Lisp.
The Schemers can work on elegant improvements, and Common Lisp can
adopt them only when it's clear that their value to the commercial
community is greater than their cost.
If Scheme eventually starts to get "messy at the edges" because of
the quantity of existing code and the high cost of changing it,
anyone in the Lisp community can easily create "Yet Another Little
Lisp" and experiment with new elegant features.
-- Robert
Thanks. I agree, these minor inconsistencies in various documents
are not serious enough to get in the way of real programming (which,
after all, is what the language is supposed to be for). They are
only a problem in the context of ridiculous Usenet imbroglios like
the one I just managed to let myself get embroiled in. (Whoops.)
-- Robert
barring any overlooked clauses which Robert will bring to my attention,
whatever it is that he's trying to distinguish between `setq' and `defvar'
at top-level is purely a matter of how _implementations_ differ in
implementing undefined semantics.
I'm sorry to see that Robert incessantly perceives any pointers to a
specification that does not support his claims, together with a refusal to
speak on behalf of or for those who defined the standard, as "vagueness".
I do not find it to be my job to over-interpret a standard in the face of
unwillingness, or even lack of interest, to read it. If a standard cannot
speak for itself, it should be improved until it does, but it is hopeless
to attempt to let things speak for themselves if the audience does not
share its context. I specifically do not claim that I understand the
totality of Common Lisp, which is why I point to authoritative sources that
I find to contradict non-authoritative examples that do not appears to show
an interest in the language, but rather in implementations, which concern
me only inso far as they implement the specification. otherwise, they have
bugs that should be reported. if legitimate disagreement over some clause
in the standard is found, the right thing is to submit a request for
clarification to ANSI about it -- there are procedures for this, and the
committee should be prepared to handle such requests. a prerequisite to
all this is of course that all parties involved in the disagreement know
precisely what the standard says on the issue (or not, as the case may be).
finally, this is not a question of whether _I_ agree or disagree with
anything Robert says or implies. the question is: is the basic assumption
on which Robert seems to build his entire case _valid_ in the context of
the language definition? if not, his case be dismissed.
I was trying to point Robert in the direction of realizing that he had no
foundation for what he was claiming with such authority. I still see no
foundation. I see no realizing he has no foundation, either, and that is
what really irks me in this case. to have the gall to conjure up some
elaborate "DAG" of arguments when his basic assumption is in question!
Robert, the HyperSpec is there for your perusal. I suggest you use to
support your case. I regret the need to play standards lawyer with you,
but you compel me to it. (compare that with what you feel forced to.)
the question is: does ANSI Common Lisp (or CLtL2 for that matter) define
the semantics of `setq' at top-level, including whether the symbol should
be declared or proclaimed special? this is a very specific question, and I
will hear no more about Robert's delusions of "vagueness" in response.
#\Erik
I agree. The standard does not specify these semantics, which permits
implementations to do whatever they want.
The most common behavior is to treat any top-level form that contains a
free reference to an undeclared variable as if it were locally declared
special, i.e.
(setq foo 3)
is treated as
(locally (declare (special foo))
(setq foo 3))
When they do this, compilers generally print a warning, e.g. "Free variable
FOO being declared SPECIAL".
As an aside, Maclisp, the Lisp dialect that CL was mostly derived from, had
the behavior that a free reference caused the variable to be declared
globally special thereafter. This was because lexical variables only
existed in the compiler; the interpreter only supported dynamic scoping.
Automatically declaring variables special was a heuristic to deal with the
fact that programmers frequently failed to put special declarations in
their code. You could still be screwed if code that binds the variable
textually precedes the code that contains the free reference, e.g.
(defun foo1 ()
(let ((*x* 3))
(bar)
*x*))
(setq *x* 0)
(defun bar ()
(incf *x*))
(defun foo2 ()
(let ((*x* 3))
(bar)
*x*))
(foo1) will always return 3, (foo2) will always return 4, and *x* will
contain the number of times (foo1) has been executed.
I think it's pretty clear how the HyperSpec is related to the AMSI
standard. It's basically the text of the standard put into HTML
(which alone would make it _derived_), plus the text of cleanup
issues. It was not derived from the standard in the sense that
Franz Inc's CLtR was derived from CLtL.
Now, if someone claims that the ANSI spec, or the HyperSpec, is
inconsistent with CLtL 2nd edition, that's not very surprising in
itself. CLtL 2 is, in effect, a snapshot of how things stood
at a certain point during the development of the standard.
The ANSI standard reflects a later point (indeed, the final
point, for that standard) and is (at least largely) separately
written text.
But is the "inconsistency" being discussed here among the actual
inconsistencies between CLtL 2 and the standard or HyperSpec?
If someone wants to show it is a real inconsistency, then, given
that the claim seems to be controversial, I wish they would do
it as follows:
Say something like "CLtL 2 says the following is true:", followed
by some text, which I'll call T. Then present the evidence that
CLtL 2 says T is true. Finally, present the evidence that the
standard (or the HyperSpec) says T is false.
When doing this, equivocation is _not_ allowed. You're not to
give any word in T one meaning when arguing that CLtL 2 says T
is true and a different meaning when arguing that the standard
or Spec says T is false.
Another claim we've seen in this discussion is that Common Lisp
does not define semantics for global variables that have not been
introduced by defvar (or something like that). If so, it's an
oversight and, in effect, an error in the standard.
To perhaps save time, let me make it clear that the only thing that
would convince me (as a former member of X3J13, etc) that it was
not an oversight (if the standard somehow fails to specify the
semantics) would be an explicit statement in the standard
that the semantics was not defined or an explicit startement in
something passed by X3J13 (and not modified or overturned later
on) that said the semantics was not defined.
>> The HyperSpec makes no attempt to be consistent with CLtL2.
>
>Now you have hit the nail on the head: I think this is the root of
>all the confusion. I wasn't saying this inconsistency is bad or
>even unnecessary -- I was just saying that it's hard to get everyone
>using the exact same definitions for certain words. I think that's
>probably the reason that Erik and I are having such difficulty
>understanding each other. It's not surprising that the two of us
>have trouble communicating, since even CLtL2 and the HyperSpec
>can't agree with each other on the exact meanings of these words.
I would like to see an argument for this along the lines I
outlined above (though, clearly, the meaning of "variable"
cannot be kept fixed since it's what's in dispute).
Bear in mind that a document can use a word in more than one
sense.
-- jd
It's not clear that the standard is entirely consistent with itself.
In section 3.1.2.1.1.2, Dynamic Variables, it says
A dynamic variable can be referenced at any time in any program;
there is no textual limitation on references to 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.
...
A dynamic variable can be referenced outside the dynamic extent of a
form that binds it. Such a variable is sometimes called a ``global
variable'' but is still in all respects just a dynamic variable whose
binding happens to exist in the global environment rather than in some
dynamic environment.
Yet in the glossary we find:
dynamic variable n. a variable the binding for which is in the
dynamic environment. See special.
Nothing about the global environment _there_.
3.1.2.1.1.2 also says
A variable is a dynamic variable if one of the following conditions hold:
* It is locally declared or globally proclaimed special.
* It occurs textually within a form that creates a dynamic binding
for a variable of the same name, and the binding is not shadowed[2]
by a form that creates a lexical binding of the same variable name.
The 1st item just above suggests that Eric may be right, so far as the
ANSI standard is concerned. However, "if" is not the same as "only if"
or "if and only if", so perhaps things aren't as clear here as they
might be. "No textual limitation" and the (so far as I know) lack
of anything that says the semantics are _not_ defined, suggests that
free refs are refs to global special variables. (N.B. special but
not _proclaimed_ special, an important distinction. Special
proclamations make all bindings of the name special, declarations don't.)
In 3.1.2.1.1, Symbols as Forms, we find:
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. There
are three kinds of variables: lexical variables, dynamic variables,
and constant variables. A variable can store one object. The main
operations on a variable are to read[1] and to write[1] its value.
There's no hint here (or anywhere else that I've found) that's
another case: variables that aren't lexical or constant yet not
dynamic either because there's hasn't been a special proclamation
or declaration. Moreover, the description of setq uses examples such
as the following without any declarations or proclamations:
;; A simple use of SETQ to establish values for variables.
(setq a 1 b 2 c 3) => 3
a => 1
b => 2
c => 3
CLtL 2 is perhaps clearer. Section 5.1.2 (p 70) says
... if the symbol occurs textually within a program construct
that creates a _binding_ for a variable of the same name, then
the reference is to the variable specified by the binding; if
no such program construct textually contains the reference,
then it is taken to refer to the special variable of that name.
The description of setq (p 121) is less clear than it might be,
since it says only that "the usual rules" determine whether
the variable being assigned to is lecical or dynamic. But I
think it's fair to conclude at least that there's not meant
to be a difference between the rules for assignment and the
rules for reference.
Section 7.1.1, Reference (p 114) says that whether the variable
is special or lexical depends on the presence of absence of a
special declaration; but I don't think that is meant to contradict
page 70.
However, the situation is muddued by the pactice in many
implementations of giving warnings on references to undeclared
free variables. Language such as "assumed to be special" is
often used. This is because implementors suspect that most
such cases are unintentional and indicate mistakes in the code.
>barring any overlooked clauses which Robert will bring to my attention,
>whatever it is that he's trying to distinguish between `setq' and `defvar'
>at top-level is purely a matter of how _implementations_ differ in
>implementing undefined semantics.
I don't think so. For one thing, there isn't much variation between
implementations. So far as I know (and I've used over a dozen Common
Lisps), they all interpret references (including in assignments) to
undeclared free variables as refrences to the special variable.
They differ in whether and when they give a warning. Most
implementations do not give a warning except when compiling.
CMU CL is an exception. I suspect it's the only one. In any
case, it has the behaviour I'd expect from p 70. E.g.
* (setq x 1)
Warning: Declaring x special.
1
* (setq x 2)
2
* (defun fx () x)
* (fx)
2
>the question is: does ANSI Common Lisp (or CLtL2 for that matter) define
>the semantics of `setq' at top-level, including whether the symbol should
>be declared or proclaimed special? this is a very specific question, and I
>will hear no more about Robert's delusions of "vagueness" in response.
Well, neither the standard not CLtL 2 makes things entirely and
explicitly clear. But I've never, before this, heard it suggested
that the semantics was not defined, not even in X3J13 discussions that
covered this area when considering the PROCLAIM-LEXICAL issue. It was
noted that the warnings mentioned above made it a pain in practice to
use undeclared free refs; but that's about as far as it went.
For instance, from PROCLAIM-LEXICAL version 2:
Description of problem:
CLtL pp. 55-56 implies that if a name (symbol) is not proclaimed or
declared special, then a free reference to that name is a reference to
the special variable of that name, while a LAMBDA-binding of that name
indicates a binding of the lexical variable of that name. This would
mean that the following program is legal and that (TST) => 4:
(defun tst ()
(setq x 3)
(funcall (let ((x 4)) #'(lambda () x))))
However, if you feed this program to many Common Lisp compilers
(including Symbolics's and DEC's), a warning message will be
produced for the SETQ, saying something like "Warning: X not
declared or bound, assuming special."
These warnings, unlike the annotations of undefined functions (which
occur only at the end of a compilation), are presented so
prominently that a user would be hard put to say that a program
which elicited such warning messages was "correct" in that
implementation. Unlike the situation with unused variables, there is
no possible declaration one can write which suppresses the warning
messages.
This disagreement between theory and practice should be mended
somehow.
Proposal (PROCLAIM-LEXICAL:CURRENT-PRACTICE):
Change the language definition (page 55?) to say that it is an error
for there to be a free reference or assignment to a name unless a
SPECIAL proclamation or declaration is in effect for that name.
This would legitimize the behavior of current implementations.
Proposal (PROCLAIM-LEXICAL:BY-THE-BOOK):
Shame implementors into going by the book. Implementations should
simply stop intimidating users who want to write code like this.
"Apparently unbound variable" warnings should be given the same
purely advisory status that "apparently undefined function" warnings
now enjoy. The exact meaning of this is of course implementation-
dependent.
[... omitting, among other things, other proposals ...]
Cost of adopting change:
CURRENT-PRACTICE: Ostensibly none, although implementations which
don't signal this as an error should be explicitly encouraged
to do so. It ought to be signalled in interpreted code as well.
BY-THE-BOOK: This would be an easy fix to the error reporting and
bookkeepping components of existing compilers. Of course it is not
a change to the language, so there is no impact on portable code.
(Later versions of the proposal use more neutral language and
went into more technical detail about the proposed semantics.
But this version is better than later ones as a guide to how
the issue was seen and the motivations for change.)
-- jd
In article <30497543...@arcana.naggum.no>,
Erik Naggum <er...@naggum.no> wrote:
> Robert Munyer's exceedingly lengthy diatribe
I wrote a lengthy article because the shorter ones didn't work.
When I tried shorter articles you refused to answer with anything
specific, and just repeated your vague and pointless assertion that
I was "wrong somewhere."
> seems to hinge on one issue: whether the semantics of `setq' at
> top-level of a variable that has not been declared special is
> defined by Common Lisp. I can't see that it is.
Good. Finally you have made a complaint that is explicit enough
to be worth discussing. But this is the first time you have
mentioned this particular complaint, and apparently it has nothing
to do with your original complaint! When you first "corrected" me
on 8/18, you did not say:
The effect of SETQ at the top level, on a variable that has
not been declared special, is not defined. Please see the
HyperSpec page on SETQ.
Instead, you said something like this:
a variable is either lexical or it is not. the "not lexical"
in Common Lisp is "special". for more information on the
environments in Common Lisp, see [the HyperSpec page "Introduction
to Environments."]
The HyperSpec page to which you referred does not say anything
about situations in which the effect of SETQ is undefined, and it
is not even the place in which one would expect to find such material
if it existed.
If your 8/18 article was really an attempt to describe your current
complaint, then it was a monumental botch, because it was not even
close to this subject -- and your abusive articles of 8/19 and 8/21
were fruitless attempts to defend this original botched article.
Since you have brought up your complaint about SETQ so late in the
discussion, I suspect that it was not your original complaint at
all. I think you probably realized you were wrong and gave up on
your original complaint -- and then tried to take advantage of your
own vagueness by secretly switching complaints in midstream.
But that's OK with me, because your new complaint is also based on
your incomplete understanding of Common Lisp. You are still wrong.
> I'd like Robert to show me how he found the semantics of this to
> be defined by the language specification since he makes so many
> conclusion based on his assumption that its semantics _is_ defined.
Wait a minute. You are proposing a side effect. The standard does
not say that this side effect exists or can exist. The burden of
proof falls on you, not on me. Tell me, how many other Lisp
constructs do you think are free to cause this undocumented side
effect? Any construct at all? Any special form? Anything that
associates a global value with a variable? Do you think that
(SET 'X 100)
and (SETF X 100)
and (SETF (SYMBOL-VALUE 'X) 100)
are free to cause this undocumented side effect, as well as
(SETQ X 100) ?
> [T]o have the gall to conjure up some elaborate "DAG" of arguments
> when his basic assumption is in question!
Gall?
You never said you were questioning my "basic assumption," nor did
you even state what you thought my basic assumption to be, until now!
> the question is: does ANSI Common Lisp (or CLtL2 for that matter)
> define the semantics of `setq' at top-level, including whether
> the symbol should be declared or proclaimed special? this is a
> very specific question, and I will hear no more about Robert's
> delusions of "vagueness" in response.
OK, before I waste any more valuable time on you, let's make it
even more specific. Let's take it out of the realm of the English
language and turn it into a code sample. This way there will be
absolutely no room left for verbal misunderstandings or midstream
changes. Consider the following code:
(setq a 100)
(let ((a '(this list is not a number)))
(eval '(1+ a)))
Which of the following best describes this code?
(a) It is legal Common Lisp and it will return 101.
(b) It is not legal Common Lisp, and it will signal an error.
(c) It is not legal Common Lisp, and its effect is undefined.
If you say (b) or (c), I will rebut. If you say (a), I will agree
with you but I will wonder what the heck you have been complaining
about!
-- Robert
#\Erik
--
my other car is a cdr
1. Summary:
It is an error for a variable which does not have a lexical binding to
not be explicitly declared special in some way (such as a declamation
or local declaration). "It is an error" has the usual meaning that
the behavior is not defined. In this particular case, this means
that implementations may or may not signal warnings or errors at
either compile or run time. No conforming program can rely on
undeclared variables being special.
It is acknowledged that this makes it difficult to use free variables in
the interpreter. Because of this, all current implementations happen to
treat undeclared free variables as special, at least in the interpreter.
At least one major implementation, CMUCL, make a global special
declamation for all free variables, whether compiled or interpreted.
This does not conflict with the above, but has the perhaps unfortunate
effect of changing the semantics of otherwise conforming code once some
user has mistakenly referenced an undeclared free variable (in
interpreted or compiled code).
2. References:
Section 3.2.2.3 Semantic Constraints, says:
All conforming programs must obey the following constraints, which are
designed to minimize the observable differences between compiled and
interpreted programs:
...
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.
At first glance, one might think this contradicts the above, but I
interpret this is specifying that the compiler must assume the variable
is lexical and look for a lexical binding. It is then, presumably, "an
error", when a compiler tries to look up a lexical binding and doesn't
find one.
Question: Jeff quoted an X3J13 issue called "PROCLAIM LEXICAL", noting
that the wording of the issue was changed over time. I cannot find an
issue with this name in Kent's excellent HyperSpec. Is it there? Can
someone give me a pointer to it?
3. Outstanding issues:
I. Once a variable has been declaimed special, how does one make it
unspecial? (Do I need to clarify why I think this is important?)
II. Consider the following:
(let ((x 1)) (compile 'foo '(lambda () x)))
I feel that on the one hand, the reference to x in the lambda is not a
variable refering to the binding of the lexical variable, but simply the
symbol x in a quoted list that happens to begin with the word lambda.
The list is not a "lambda expression". On the other hand, the
definition of COMPILE specifically says that it IS a lambda expression.
Also, this list must be compiled in the compilation environment. The
end of section 3.2.1 Compiler Terminology says that COMPILE is a
run-time compiler for which the run-time environment and compiler
startup environment are the same, and that the compilation environment
inherits (ultimately) from the compiler startup environment. Since the
run-time environment in which compile was called clearly had a lexical
binding for X, this is also true in the compilation environment.
The dictionary defintion for COMPILE says that the lambda expression is
coerced to a function, and coercing a lambda-expression to a function in
the body of the LET would also ordinarily enclose the binding of X.
It then goes on to say, though, that:
The consequences are undefined if the lexical environment surrounding
the function to be compiled contains any bindings other than those for
macros, symbol macros, or declarations.
Since this is the most specific statement, it takes precedence.
However, I would feel more comfortable if there was some acknowledgement
that the second argument to COMPILE was not a full fledged lambda
expression and that its coercion to a funciton did not follow the usual
semantics regarding the capture of lexical bindings.
I note that since the consequence of this case are undefined, it does
leave open the possibility that an implemenation might make use of the
lexical binding. Of course, no conforming program could rely on this
extension, and it raises another issue. If the compiler can reference
lexical bindings in a run-time environment outside the scope of the
compiler, then the reference I cite above (section 2) would want to be
handled by such implementations by doing a run-time lexical variable
lookup, as though in an interpreter. This, in turn, raises the issue of
run-time maniplulation of environments by user code. While it seems
that "madness this way lies", I could imagine wanting to use a debugger
in which the lexical (and dynamic?) environment from the current stack
frame were available to me in evaluating forms within the debugger. (I
remember being shocked as freshman that this was NOT what happened.) One
might make use of some of these features to write such a debugger.
So, the question is: Is this analysis correct? Is the behavior of
undeclared non-lexical variables undefined, and does this include X in
the COMPILE example? Is an implementation free to define the behavior
consistent with the concept of looking (at run or compile time) for a
lexical variable and using it, and failing that, to silently use the
global value?
-h
---------------------------------------------------------
In article <30501136...@arcana.naggum.no>,
Erik Naggum <er...@naggum.no> wrote:
> Robert Munyer's incessant bickering has made me realize it was
> a mistake to try to discuss this with him.
Again you have weaseled out of answering my questions, and chosen
to insult me instead. Trying to have a fair debate with you is
like trying to catch a slippery fish with one's bare hands. Every
time I try to get you to commit to ANYTHING, you evade my questions
and respond with insults or sarcasm.
> I apologize for the spectacle.
As well you should. You have a lot to learn about how to participate
in a discussion without antagonizing people. During the height of
this "spectacle," I received an e-mail from another reader of the
newsgroup (whom I shall not name). He referred to you as a "pig"
who has a "history of arrogance, stubbornness, and irascibility."
I suspect he is just one of a long line of people whom you have
abused in various newsgroups, for no reason at all.
My own experience is a case in point. I didn't make any disparaging
statements about you until after you wrote three articles against
me. You "corrected" me once, and then attacked me several times,
in articles which grew increasingly condescending and sarcastic --
all because I made use of an aspect of Common Lisp that you didn't
understand, in an article that wasn't even directed at you.
Barry Margolin has also accused me of being wrong in this thread,
but he managed to do it without being rude, condescending, snide,
sarcastic, and evasive. So I can still have a polite debate with
him, and not have to waste my time in flame wars. You should look
through his articles, and take a lesson. Maybe then you will not
end up convincing any more people that you are a "pig."
I hope your first sentence above means that you are going to get
out of this thread, and let the rest of us discuss technical issues
in peace.
-- Robert
In article <DwrDL...@cogsci.ed.ac.uk>,
Jeff Dalton <je...@cogsci.ed.ac.uk> wrote:
> It's not clear that the standard is entirely consistent with
> itself.
Afraid I have to agree. In particular there seem to be a few
situations where it's hard (or even impossible?) to reconcile the
text with the glossary.
> 3.1.2.1.1.2 also says
>
> A variable is a dynamic variable if one of the following
> conditions hold:
>
> * It is locally declared or globally proclaimed special.
>
> * It occurs textually within a form that creates a dynamic
> binding for a variable of the same name, and the binding
> is not shadowed[2] by a form that creates a lexical binding
> of the same variable name.
>
> The 1st item just above suggests that Eric may be right, so far
> as the ANSI standard is concerned. However, "if" is not the same
> as "only if" or "if and only if", so perhaps things aren't as
> clear here as they might be. "No textual limitation" and the
> (so far as I know) lack of anything that says the semantics are
> _not_ defined, suggests that free refs are refs to global special
> variables. (N.B. special but not _proclaimed_ special, an
> important distinction. Special proclamations make all bindings
> of the name special, declarations don't.)
Based on those last two sentences I think you actually agree with
me, not with Erik. Erik's latest attempt at spin control seems to
be a claim that an implementation is allowed (under both CLtL2 and
the ANSI standard) to PROCLAIM a symbol special, if you use SETQ
to give it a global value. I'm not sure if Erik thinks this also
applies to SET and SETF and (SETF SYMBOL-VALUE), because he refuses
to answer my questions.
> In 3.1.2.1.1, Symbols as Forms, we find:
>
> 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. There are three kinds of variables: lexical variables,
> dynamic variables, and constant variables. A variable can store
> one object. The main operations on a variable are to read[1]
> and to write[1] its value.
>
> There's no hint here (or anywhere else that I've found) that's
> another case: variables that aren't lexical or constant yet not
> dynamic either because there's hasn't been a special proclamation
> or declaration.
Remember that in the HyperSpec, the unadorned term "variable" refers
to a binding, not to the symbol that names the binding. I am not
saying that a BINDING can be something other than lexical or constant
or dynamic; I am saying that a NAME can have a lexical binding and
a dynamic binding at the same time -- and in fact, that dynamic
binding can be global. If you assign a global value to a variable
name without proclaiming that name to be special, then you can
still have lexical bindings on that same variable name.
> Moreover, the description of setq uses examples such as the
> following without any declarations or proclamations:
>
> ;; A simple use of SETQ to establish values for variables.
> (setq a 1 b 2 c 3) => 3
> a => 1
> b => 2
> c => 3
The three bindings created here are global and therefore dynamic.
But the three symbols have not been proclaimed special, so they
are still available for either lexical or dynamic binding (or both)
in the future of this Lisp session.
> CLtL 2 is perhaps clearer. Section 5.1.2 (p 70) says
>
> ... if the symbol occurs textually within a program construct
> that creates a _binding_ for a variable of the same name, then
> the reference is to the variable specified by the binding; if
> no such program construct textually contains the reference,
> then it is taken to refer to the special variable of that name.
Yes, I think this is better and clearer than the corresponding
section of the HyperSpec.
> The description of setq (p 121) is less clear than it might be,
> since it says only that "the usual rules" determine whether the
> variable being assigned to is lecical or dynamic. But I think
> it's fair to conclude at least that there's not meant to be a
> difference between the rules for assignment and the rules for
> reference.
I agree. To have assignment work differently would seem "strange."
> However, the situation is muddued by the pactice in many
> implementations of giving warnings on references to undeclared
> free variables. Language such as "assumed to be special" is
> often used. This is because implementors suspect that most such
> cases are unintentional and indicate mistakes in the code.
Actually, I don't find this warning to be muddy -- as long as you
understand that the phrase "assumed to be special" refers to that
one particular reference, not to EVERY binding or reference that
happens to have the same name. This warning just means that
(defun foo () x)
is replaced with
(defun foo () (declare (special x)) x)
rather than with
(declaim (special x))
(defun foo () x)
> > barring any overlooked clauses which Robert will bring to my
> > attention, whatever it is that he's trying to distinguish
> > between `setq' and `defvar' at top-level is purely a matter of
> > how _implementations_ differ in implementing undefined semantics.
>
> I don't think so. For one thing, there isn't much variation
> between implementations. So far as I know (and I've used over
> a dozen Common Lisps), they all interpret references (including
> in assignments) to undeclared free variables as refrences to the
> special variable.
Right. This behavior is specified by CLtL2 section 5.1.2:
The general rule is that if the symbol occurs textually within
a program construct that creates a binding for a variable of
the same name, then the reference is to the variable specified
by the binding; if no such program construct textually contains
the reference, then it is taken to refer to the special variable
of that name.
> They differ in whether and when they give a warning. Most
> implementations do not give a warning except when compiling.
> CMU CL is an exception. I suspect it's the only one. In any
> case, it has the behaviour I'd expect from p 70. E.g.
>
> * (setq x 1)
> Warning: Declaring x special.
> 1
>
> * (setq x 2)
> 2
>
> * (defun fx () x)
>
> * (fx)
> 2
An important question here is whether the symbol X was PROCLAIMED
to be special. A proclamation is a type of declaration, so the
warning message above doesn't really tell us whether SETQ proclaimed
the symbol X to be special, or merely declared that one particular
use of X to be special. And the function FX doesn't help us,
because it would always return 2, regardless of whether the symbol
X has been proclaimed to be special.
Apparently you have a CMU CL handy. If so, could you please use
it to evaluate the following:
(let ((data '(( defparameter (defparameter x nil))
( defvar (defvar x nil))
( set (set 'x nil))
( setf (setf x nil))
((setf symbol-value) (setf (symbol-value 'x) nil))
( setq (setq x nil)))))
(let ((does '()) (doesnt '()))
(dolist (d data)
(let ((desc (first d)) (form (second d)) (name (gensym)))
(eval (subst name 'x form))
(if (eval `(let ((,name t))
(declare (ignore-if-unused ,name))
(symbol-value ',name)))
(push desc does)
(push desc doesnt))))
(let ((fmt "~&These ~a: ~:[~%~4t[none]~;~:*~{~%~4t~s~}~]"))
(format t fmt "proclaim special" (nreverse does))
(format t fmt "do not" (nreverse doesnt)))))
and let us know what it says? The results should be:
These proclaim special:
DEFPARAMETER
DEFVAR
These do not:
SET
SETF
(SETF SYMBOL-VALUE)
SETQ
In fact, since you've used over a dozen Common Lisps, you probably
have several of them handy. It would be great if you could evaluate
the above code in each of them. Other people reading this, please
feel free to contribute results from whichever implementation of
Common Lisp you are using.
> > the question is: does ANSI Common Lisp (or CLtL2 for that
> > matter) define the semantics of `setq' at top-level, including
> > whether the symbol should be declared or proclaimed special?
>
> Well, neither the standard not CLtL 2 makes things entirely and
> explicitly clear.
My own understanding is that no side effect is allowed unless it
is documented. Therefore lack of specific mention means that the
side effect is not allowed.
Otherwise, all hell would break loose. You could have any kind of
construct producing any kind of side effect, because the standard
very rarely states explicitly that a certain construct will not
have a certain side effect. It is just taken for granted that only
documented side effects can exist.
Also, any implementation which follows Erik's suggestion, and
proclaims symbols special when not explicitly required to by the
standard, will be unable to evaluate standard example code
successfully. For example, see the code in the section on EVAL:
http://www.harlequin.com/books/HyperSpec/Body/fun_eval.html
You can't argue that an implementation is correct, if it can't even
evaluate the code examples in the standard!
> But I've never, before this, heard it suggested that the semantics
> was not defined, not even in X3J13 discussions that covered this
> area when considering the PROCLAIM-LEXICAL issue. It was noted
> that the warnings mentioned above made it a pain in practice to
> use undeclared free refs; but that's about as far as it went.
>
> For instance, from PROCLAIM-LEXICAL version 2:
This PROCLAIM-LEXICAL document to which you refer is very interesting.
This is the first time I've heard that anyone on the committee has
addressed this issue directly. PROCLAIM-LEXICAL is not mentioned
in the standard; does that mean the issue never came to a vote?
I do not know who wrote this document or when, so I'll reply to it
as if it had been written today. Please note that if there are
times when I seem to be criticizing the author of PROCLAIM-LEXICAL,
I am not criticizing the real author, but rather some imaginary
hypothetical author whom I pretend to have written this today.
> Description of problem:
>
> CLtL pp. 55-56 implies that if a name (symbol) is not proclaimed
> or declared special, then a free reference to that name is a
> reference to the special variable of that name, while a
> LAMBDA-binding of that name indicates a binding of the lexical
> variable of that name. This would mean that the following
> program is legal and that (TST) => 4:
>
> (defun tst ()
> (setq x 3)
> (funcall (let ((x 4)) #'(lambda () x))))
Yes.
> However, if you feed this program to many Common Lisp compilers
> (including Symbolics's and DEC's), a warning message will be
> produced for the SETQ, saying something like "Warning: X not
> declared or bound, assuming special."
This is not a problem, merely a warning. These two compilers
evaluate this example code correctly. They do not proclaim the
symbol X to be special. Their "assuming" affects only the first
occurrence of X, not the others. Otherwise they would fail the
test function TST and return 3.
> These warnings, unlike the annotations of undefined functions
> (which occur only at the end of a compilation), are presented
> so prominently that a user would be hard put to say that a
> program which elicited such warning messages was "correct" in
> that implementation. Unlike the situation with unused variables,
> there is no possible declaration one can write which suppresses
> the warning messages.
Not true. The user could insert (DECLARE (SPECIAL X)) at the
beginning of TST; its behavior would be unchanged, but no warnings
would be issued.
> This disagreement between theory and practice should be mended
> somehow.
>
> Proposal (PROCLAIM-LEXICAL:CURRENT-PRACTICE):
>
> Change the language definition (page 55?) to say that it is an
> error for there to be a free reference or assignment to a name
> unless a SPECIAL proclamation or declaration is in effect for
> that name.
>
> This would legitimize the behavior of current implementations.
This proposal is NOT necessary to legitimize the behavior of the
"current implementations" described here, since they only issue a
warning rather than an error. The author's belief that "current
practice" is somehow different from "by the book" is based solely
on the idea that the warning messages are somehow too prominent to
be seen as mere warnings.
In truth, this proposal should not be called "current practice" at
all, because it would invalidate programs that are currently correct
according to the book AND according to the "current implementations"
described here.
> Proposal (PROCLAIM-LEXICAL:BY-THE-BOOK):
>
> Shame implementors into going by the book. Implementations
> should simply stop intimidating users who want to write code
> like this. "Apparently unbound variable" warnings should be
> given the same purely advisory status that "apparently undefined
> function" warnings now enjoy. The exact meaning of this is of
> course implementation- dependent.
This proposal "BY-THE-BOOK" appears to be based on an understanding
of Common Lisp semantics that is identical to my own. (Although
I have not espoused the actual proposal, i. e. that the warnings
should me made less intimidating).
> [... omitting, among other things, other proposals ...]
>
> Cost of adopting change:
>
> CURRENT-PRACTICE: Ostensibly none, although implementations
> which don't signal this as an error should be explicitly
> encouraged to do so. It ought to be signalled in interpreted
> code as well.
"Ostensibly" indeed! The cost of adopting CURRENT-PRACTICE is not
"none." Certain users would be required to insert special declarations
in certain places in order to avoid errors. Currently they need
to insert these declarations only to avoid WARNINGS. The claim
that the cost is "none" is true only if you assume that all users
have already inserted these declarations in order to avoid the
warning messages. (Or perhaps the author was only considering cost
to implementors, rather than cost to users.)
> BY-THE-BOOK: This would be an easy fix to the error reporting
> and bookkeepping components of existing compilers. Of course
> it is not a change to the language, so there is no impact on
> portable code.
>
> (Later versions of the proposal use more neutral language and
> went into more technical detail about the proposed semantics.
> But this version is better than later ones as a guide to how the
> issue was seen and the motivations for change.)
What ever happened to these proposals? Were they voted on?
-- Robert
No way. I've seen nothing that says or implies that it is an error,
and it's odd that you regard this paragraph of yours as a summary. It
certainly doesn't reflect the discussion *I've* seen.
> "It is an error" has the usual meaning that
> the behavior is not defined.
But people have been using that the other way around, as if "not
explicitly defined anywhere" meant "is an error".
> In this particular case, this means
> that implementations may or may not signal warnings or errors at
> either compile or run time.
I have seen no justification for signalling an error. I'm not sure in
what cases warnings are permitted, but in practice they certainly
include cases that are allowed in conforming code and that are not
"an error".
> No conforming program can rely on
> undeclared variables being special.
Why not? For instance, this should work:
1. (setf (symbol-value 'x) 100) => 100
2. (locally (declare (special x)) x) => 100
It's arguable that x has been declared special in line 2,
but it certainly hasn't been in line 1, and I've never seen
even a warning (not even in CMUCL) for such things as line 1.
Yet it's clear from the HyperSpec and CLtL that symbol-value
reads and writes the value of the dynamic (ie, special) variable.
So x must have been special before any declaration or proclamation
had occurred. (And line 2 is relying on this.)
>It is acknowledged that this makes it difficult to use free variables in
>the interpreter.
It is? By?
> Because of this, all current implementations happen to
>treat undeclared free variables as special, at least in the interpreter.
Can you tell me one that doesn't do this in the compiler? At most,
there's a warning when the code is compiled (so far as I've seen).
>At least one major implementation, CMUCL, make a global special
>declamation for all free variables, whether compiled or interpreted.
Humm. It shouldn't do that.
>2. References:
>
>Section 3.2.2.3 Semantic Constraints, says:
>
> All conforming programs must obey the following constraints, which are
>designed to minimize the observable differences between compiled and
> interpreted programs:
> ...
> 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.
>
>At first glance, one might think this contradicts the above, but I
>interpret this is specifying that the compiler must assume the variable
>is lexical and look for a lexical binding. It is then, presumably, "an
>error", when a compiler tries to look up a lexical binding and doesn't
>find one.
Note that it says "any _binding_" (emphasis added) and not "any
reference". So if the compiler sees
(let ((x 1))
...)
and there's no special declaration/proclamation in the compilation
env, the x is bound as a lexical variable.
>Question: Jeff quoted an X3J13 issue called "PROCLAIM LEXICAL", noting
>that the wording of the issue was changed over time. I cannot find an
>issue with this name in Kent's excellent HyperSpec. Is it there? Can
>someone give me a pointer to it?
It wasn't passed, hence isn't in the HyperSpec. But that doesn't
invalidate its description of the problem and the proposals.
>3. Outstanding issues:
>
> I. Once a variable has been declaimed special, how does one make it
>unspecial? (Do I need to clarify why I think this is important?)
There's no standard way to do so.
> II. Consider the following:
> (let ((x 1)) (compile 'foo '(lambda () x)))
Let's please not get into a discussion of COMPILE. It will complicate
everything for little gain.
-- jd
In article <DwrDL...@cogsci.ed.ac.uk>,
Jeff Dalton <je...@cogsci.ed.ac.uk> wrote:
> It's not clear that the standard is entirely consistent with
> itself.
Afraid I have to agree. In particular there seem to be a few
situations where it's hard (or even impossible?) to reconcile the
text with the glossary.
> 3.1.2.1.1.2 also says
>
> A variable is a dynamic variable if one of the following
> conditions hold:
>
> * It is locally declared or globally proclaimed special.
>
> * It occurs textually within a form that creates a dynamic
> binding for a variable of the same name, and the binding
> is not shadowed[2] by a form that creates a lexical binding
> of the same variable name.
>
> The 1st item just above suggests that Eric may be right, so far
> as the ANSI standard is concerned. However, "if" is not the same
> as "only if" or "if and only if", so perhaps things aren't as
> clear here as they might be. "No textual limitation" and the
> (so far as I know) lack of anything that says the semantics are
> _not_ defined, suggests that free refs are refs to global special
> variables. (N.B. special but not _proclaimed_ special, an
> important distinction. Special proclamations make all bindings
> of the name special, declarations don't.)
Based on those last two sentences I think you actually agree with
me, not with Erik. Erik's latest attempt at spin control seems to
be a claim that an implementation is allowed (under both CLtL2 and
the ANSI standard) to PROCLAIM a symbol special, if you use SETQ
to give it a global value. I'm not sure if Erik thinks this also
applies to SET and SETF and (SETF SYMBOL-VALUE), because he refuses
to answer my questions.
> In 3.1.2.1.1, Symbols as Forms, we find:
>
> 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. There are three kinds of variables: lexical variables,
> dynamic variables, and constant variables. A variable can store
> one object. The main operations on a variable are to read[1]
> and to write[1] its value.
>
> There's no hint here (or anywhere else that I've found) that's
> another case: variables that aren't lexical or constant yet not
> dynamic either because there's hasn't been a special proclamation
> or declaration.
Remember that in the HyperSpec, the unadorned term "variable" refers
to a binding, not to the symbol that names the binding. I am not
saying that a BINDING can be something other than lexical or constant
or dynamic; I am saying that a NAME can have a lexical binding and
a dynamic binding at the same time -- and in fact, that dynamic
binding can be global. If you assign a global value to a variable
name without proclaiming that name to be special, then you can
still have lexical bindings on that same variable name.
> Moreover, the description of setq uses examples such as the
> following without any declarations or proclamations:
>
> ;; A simple use of SETQ to establish values for variables.
> (setq a 1 b 2 c 3) => 3
> a => 1
> b => 2
> c => 3
The three bindings created here are global and therefore dynamic.
But the three symbols have not been proclaimed special, so they
are still available for either lexical or dynamic binding (or both)
in the future of this Lisp session.
> CLtL 2 is perhaps clearer. Section 5.1.2 (p 70) says
>
> ... if the symbol occurs textually within a program construct
> that creates a _binding_ for a variable of the same name, then
> the reference is to the variable specified by the binding; if
> no such program construct textually contains the reference,
> then it is taken to refer to the special variable of that name.
Yes, I think this is better and clearer than the corresponding
section of the HyperSpec.
> The description of setq (p 121) is less clear than it might be,
> since it says only that "the usual rules" determine whether the
> variable being assigned to is lecical or dynamic. But I think
> it's fair to conclude at least that there's not meant to be a
> difference between the rules for assignment and the rules for
> reference.
I agree. To have assignment work differently would seem "strange."
> However, the situation is muddued by the pactice in many
> implementations of giving warnings on references to undeclared
> free variables. Language such as "assumed to be special" is
> often used. This is because implementors suspect that most such
> cases are unintentional and indicate mistakes in the code.
Actually, I don't find this warning to be muddy -- as long as you
understand that the phrase "assumed to be special" refers to that
one particular reference, not to EVERY binding or reference that
happens to have the same name. This warning just means that
(defun foo () x)
is replaced with
(defun foo () (declare (special x)) x)
rather than with
(declaim (special x))
(defun foo () x)
> > barring any overlooked clauses which Robert will bring to my
> > attention, whatever it is that he's trying to distinguish
> > between `setq' and `defvar' at top-level is purely a matter of
> > how _implementations_ differ in implementing undefined semantics.
>
> I don't think so. For one thing, there isn't much variation
> between implementations. So far as I know (and I've used over
> a dozen Common Lisps), they all interpret references (including
> in assignments) to undeclared free variables as refrences to the
> special variable.
Right. This behavior is specified by CLtL2 section 5.1.2:
The general rule is that if the symbol occurs textually within
a program construct that creates a binding for a variable of
the same name, then the reference is to the variable specified
by the binding; if no such program construct textually contains
the reference, then it is taken to refer to the special variable
of that name.
> They differ in whether and when they give a warning. Most
> implementations do not give a warning except when compiling.
> CMU CL is an exception. I suspect it's the only one. In any
> case, it has the behaviour I'd expect from p 70. E.g.
>
> * (setq x 1)
> Warning: Declaring x special.
> 1
>
> * (setq x 2)
> 2
>
> * (defun fx () x)
>
> * (fx)
> 2
An important question here is whether the symbol X was PROCLAIMED
to be special. A proclamation is a type of declaration, so the
warning message above doesn't really tell us whether SETQ proclaimed
the symbol X to be special, or merely declared that one particular
use of X to be special. And the function FX doesn't help us,
because it would always return 2, regardless of whether the symbol
X has been proclaimed to be special.
Apparently you have a CMU CL handy. If so, could you please use
it to evaluate the following:
(let ((data '(( defparameter (defparameter x nil))
( defvar (defvar x nil))
( set (set 'x nil))
( setf (setf x nil))
((setf symbol-value) (setf (symbol-value 'x) nil))
( setq (setq x nil)))))
(let ((does '()) (doesnt '()))
(dolist (d data)
(let ((desc (first d)) (form (second d)) (name (gensym)))
(eval (subst name 'x form))
(if (eval `(let ((,name t))
(declare (ignorable ,name))
(symbol-value ',name)))
(push desc does)
(push desc doesnt))))
(let ((fmt "~&These ~a: ~:[~%~4t[none]~;~:*~{~%~4t~s~}~]"))
(format t fmt "proclaim special" (nreverse does))
(format t fmt "do not" (nreverse doesnt)))))
and let us know what it says? The results should be:
These proclaim special:
DEFPARAMETER
DEFVAR
These do not:
SET
SETF
(SETF SYMBOL-VALUE)
SETQ
In fact, since you've used over a dozen Common Lisps, you probably
have several of them handy. It would be great if you could evaluate
the above code in each of them. Other people reading this, please
feel free to contribute results from whichever implementation of
Common Lisp you are using.
> > the question is: does ANSI Common Lisp (or CLtL2 for that
> > matter) define the semantics of `setq' at top-level, including
> > whether the symbol should be declared or proclaimed special?
>
> Well, neither the standard not CLtL 2 makes things entirely and
> explicitly clear.
My own understanding is that no side effect is allowed unless it
is documented. Therefore lack of specific mention means that the
side effect is not allowed.
Otherwise, all hell would break loose. You could have any kind of
construct producing any kind of side effect, because the standard
very rarely states explicitly that a certain construct will not
have a certain side effect. It is just taken for granted that only
documented side effects can exist.
Also, any implementation which follows Erik's suggestion, and
proclaims symbols special when not explicitly required to by the
standard, will be unable to evaluate standard example code
successfully. For example, see the code in the section on EVAL:
http://www.harlequin.com/books/HyperSpec/Body/fun_eval.html
You can't argue that an implementation is correct, if it can't even
evaluate the code examples in the standard!
> But I've never, before this, heard it suggested that the semantics
> was not defined, not even in X3J13 discussions that covered this
> area when considering the PROCLAIM-LEXICAL issue. It was noted
> that the warnings mentioned above made it a pain in practice to
> use undeclared free refs; but that's about as far as it went.
>
> For instance, from PROCLAIM-LEXICAL version 2:
This PROCLAIM-LEXICAL document to which you refer is very interesting.
This is the first time I've heard that anyone on the committee has
addressed this issue directly. PROCLAIM-LEXICAL is not mentioned
in the standard; does that mean the issue never came to a vote?
I do not know who wrote this document or when, so I'll reply to it
as if it had been written today. Please note that if there are
times when I seem to be criticizing the author of PROCLAIM-LEXICAL,
I am not criticizing the real author, but rather some imaginary
hypothetical author whom I pretend to have written this today.
> Description of problem:
>
> CLtL pp. 55-56 implies that if a name (symbol) is not proclaimed
> or declared special, then a free reference to that name is a
> reference to the special variable of that name, while a
> LAMBDA-binding of that name indicates a binding of the lexical
> variable of that name. This would mean that the following
> program is legal and that (TST) => 4:
>
> (defun tst ()
> (setq x 3)
> (funcall (let ((x 4)) #'(lambda () x))))
Yes.
> However, if you feed this program to many Common Lisp compilers
> (including Symbolics's and DEC's), a warning message will be
> produced for the SETQ, saying something like "Warning: X not
> declared or bound, assuming special."
This is not a problem, merely a warning. These two compilers
evaluate this example code correctly. They do not proclaim the
symbol X to be special. Their "assuming" affects only the first
occurrence of X, not the others. Otherwise they would fail the
test function TST and return 3.
> These warnings, unlike the annotations of undefined functions
> (which occur only at the end of a compilation), are presented
> so prominently that a user would be hard put to say that a
> program which elicited such warning messages was "correct" in
> that implementation. Unlike the situation with unused variables,
> there is no possible declaration one can write which suppresses
> the warning messages.
Not true. The user could insert (DECLARE (SPECIAL X)) at the
beginning of TST; its behavior would be unchanged, but no warnings
would be issued.
> This disagreement between theory and practice should be mended
> somehow.
>
> Proposal (PROCLAIM-LEXICAL:CURRENT-PRACTICE):
>
> Change the language definition (page 55?) to say that it is an
> error for there to be a free reference or assignment to a name
> unless a SPECIAL proclamation or declaration is in effect for
> that name.
>
> This would legitimize the behavior of current implementations.
This proposal is NOT necessary to legitimize the behavior of the
"current implementations" described here, since they only issue a
warning rather than an error. The author's belief that "current
practice" is somehow different from "by the book" is based solely
on the idea that the warning messages are somehow too prominent to
be seen as mere warnings.
In truth, this proposal should not be called "current practice" at
all, because it would invalidate programs that are currently correct
according to the book AND according to the "current implementations"
described here.
> Proposal (PROCLAIM-LEXICAL:BY-THE-BOOK):
>
> Shame implementors into going by the book. Implementations
> should simply stop intimidating users who want to write code
> like this. "Apparently unbound variable" warnings should be
> given the same purely advisory status that "apparently undefined
> function" warnings now enjoy. The exact meaning of this is of
> course implementation- dependent.
This proposal "BY-THE-BOOK" appears to be based on an understanding
of Common Lisp semantics that is identical to my own. (Although
I have not espoused the actual proposal, i. e. that the warnings
should me made less intimidating).
> [... omitting, among other things, other proposals ...]
>
> Cost of adopting change:
>
> CURRENT-PRACTICE: Ostensibly none, although implementations
> which don't signal this as an error should be explicitly
> encouraged to do so. It ought to be signalled in interpreted
> code as well.
"Ostensibly" indeed! The cost of adopting CURRENT-PRACTICE is not
"none." Certain users would be required to insert special declarations
in certain places in order to avoid errors. Currently they need
to insert these declarations only to avoid WARNINGS. The claim
that the cost is "none" is true only if you assume that all users
have already inserted these declarations in order to avoid the
warning messages. (Or perhaps the author was only considering cost
to implementors, rather than cost to users.)
> BY-THE-BOOK: This would be an easy fix to the error reporting
> and bookkeepping components of existing compilers. Of course
> it is not a change to the language, so there is no impact on
> portable code.
>
> (Later versions of the proposal use more neutral language and
> went into more technical detail about the proposed semantics.
> But this version is better than later ones as a guide to how the
> issue was seen and the motivations for change.)
What ever happened to these proposals? Were they voted on?
-- Robert
if you should return to technical discussions, please, try to respect that
those with whom you try to discuss anything technical might want to refer
you to authoritative documents and standards instead of including them in
their replies or paraphrasing them with an added chance of introducing more
confusion. you strongly suggest that you have higher regard and respect
for USENET contributions than for standards documents, and this is an
attitude so mind-bogglingly irrational that if I come across as saying "you
are stupid, Robert Munyer", it is because that is exactly what I think.
BTW, anonymous references to private communication, ostensibly to avoid
being the one to slander somebody else, is the best evidence yet to be
found on USENET of how low a person can get. such behavior reveals an
amazingly cavalier attitude to reproducibility of observations and
credibility of conclusions, and points to a fundamental misunderstanding of
how legitimate observations and conclusions are made. it is no wonder at
all that such a person is incapable of reading a standards document to
learn of the facts of a specification, when he obviously believes that it
furthers his cause to make such pathetic attacks solely on his opponent.
and to have the gall to make the unfounded claim that he wants to discuss
technical issues at the same time is...
you are in fact wrong on your technical points, Robert Munyer. there is
nothing more than "read the fine manual" to tell you. since you refuse to
do that, and instead continue to pose irrelevant questions about what
people think or believe, based on your own misunderstood assumptions, what
exactly did you expect to receive? what would you do with the answers you
got? would you use them in anonymous references in discussions with your
colleagues that you are somehow correct in your assumptions? would you at
any one point go and consult the specification to learn how things _should_
have been done, instead doing a Gallup poll on what a representative sample
of the population might think? standards are written by the best people we
can find. anybody at all can have opinions. this is why we have standards
written by experts instead of Gallup polls on USENET every time we wish to
know what Common Lisp, the language, specifies.
and it is true, I find unbridled display of arrogant ignorance to be the
worst aspect of USENET. and it is true, I do treat people who refuse to
listen to authoritative sources and instead go on to ask _people_ what they
think, as fundamentally misguided and extremely unlikely to produce
anything of reasonable value in a discussion, because they discuss not what
is, but what people believe.
finally, Robert Munyer, you do most emphatically not _have_ to waste your
time in flame wars. if you _want_ to waste your time in flame wars, that
is your very own choice. sometimes, it is more effective to shut up than
to continue to make the crux of your argument that somebody else is a
"pig".
you said you had a technical argument. I'll believe it when I see it. I
don't think it is possible to have technical discussion with people whose
mission it is to convince the world of their own personal misconceptions,
including, but not limited to meaningless and pathetic slandering of
others. I think a technical discussion must refer to something that is
impersonal, such as a standard specification for a programming language.
In article <32231138...@elwoodcorp.com>,
Howard R. Stearns <how...@elwoodcorp.com> wrote:
> 1. Summary:
>
> It is an error for a variable which does not have a lexical
> binding to not be explicitly declared special in some way (such
> as a declamation or local declaration). "It is an error" has
> the usual meaning that the behavior is not defined. In this
> particular case, this means that implementations may or may
> not signal warnings or errors at either compile or run time.
> No conforming program can rely on undeclared variables being
> special.
Sorry, none of the above is true. There is plenty of code in the
standard that does exactly what you are saying cannot be done. I
understand how you came to this conclusion (see below) but it is
not correct.
> At least one major implementation, CMUCL, make a global special
> declamation for all free variables, whether compiled or interpreted.
If this is true, it is a bug in CMUCL.
If anyone reading this has a CMU CL handy, It would be helpful if
you could use it to evaluate the test code in my 8/28 article
(message id <500t58$r...@Mars.mcs.com>, the code that starts with
"(let ((data '((") and let us know what it says.
> 2. References:
>
> Section 3.2.2.3 Semantic Constraints, says:
>
> All conforming programs must obey the following constraints,
> which are designed to minimize the observable differences
> between compiled and interpreted programs:
> ...
> 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.
Looking at that last paragraph, I can see why you came to your
conclusion. Taken out of context, you might think that it is a
blanket statement about variable access. But there are two details
that you are missing.
One is that this paragraph refers to BINDINGS, not to REFERENCES.
The other detail is that you need to interpret your quoted paragraph
in the proper context. It is not in the part of the standard that
describes variable access rules; it is in the part that describes
the compilation environment. This section of the standard is
derived from COMPILE-ENVIRONMENT-CONSISTENCY and its purpose is to
say that special declarations, when they are meaningful, must be
available in the compilation environment (rather than in some other
environment) and that they must be available "soon enough" to be
used by the compiler. Consider this code snippet:
? (defun foo () x)
FOO
? (defun bar () (let ((x 5)) (foo)))
BAR
? (proclaim '(special x))
NIL
? (bar)
5
The purpose of the compilation environment section you quoted is
to explain that the above code, although it might work in an
interpreted Common Lisp, cannot be compiled. There are two reasons
for this: (a) PROCLAIM does not make declarations available in
the compilation environment. You need to either enclose it in
EVAL-WHEN or change it to DECLAIM. (b) The declaration is not made
"soon enough." It must be placed BEFORE the definition of BAR.
Notice I did not say that it has to be placed before the definition
of FOO. FOO does not need the declaration, because FOO does not
create a binding. FOO's reference to X is automatically special,
with or without a declaration.
If you look back at the standard you will notice that the paragraph
you omitted (and replaced with three periods) says simply that
macros must be defined before they are needed, and that their
definitions must be available in the compilation environment.
Likewise the other paragraph (which you did not omit) says simply
that special declarations must be made before they are needed, and
that they must be available in the compilation environment.
The requirement that special variables must be declared applies
only in situations where a special declaration is meaningful. In
FOO the declaration would be meaningless so the rule does not apply.
In BAR the rule applies.
(Once again, it seems, the explanation in CLtL2 is a bit clearer
and easier to understand than the newer one in the HyperSpec.)
This is the corresponding text from CLtL2 section 25.1.3:
X3J13 voted in June 1989 (COMPILE-ENVIRONMENT-CONSISTENCY) to
specify what information must be available at compile time for
correct compilation and what need not be available until run
time.
The following information must be present in the compile-time
environment for a program to be compiled correctly. This
information need not also be present in the run-time environment.
In conforming code, macros referenced in the code being
compiled must have been previously defined in the
compile-time environment. The compiler must treat as a
function call any form that is a list whose car is a
symbol that does not name a macro or special form. (This
implies that setf methods must also be available at
compile time.)
In conforming code, proclamations for special variables
must be made in the compile-time environment before any
bindings of those variables are processed by the compiler.
The compiler must treat any binding of an undeclared
variable as a lexical binding.
> 3. Outstanding issues:
>
> I. Once a variable has been declaimed special, how does one make
> it unspecial? (Do I need to clarify why I think this is
> important?)
When a symbol has been declaimed special, it is special forever.
But you can delete the symbol from its package with UNINTERN. Once
you have done this, the next time you type the symbol name the
reader will create a new (non-special) symbol with the same name.
But any data and code that used the old symbol will continue to
use the old symbol (until you redefine it and thus pass it through
the reader again).
Here is a demonstration:
(defun special? (sym)
(check-type sym symbol)
(eval `(let ((,sym nil))
(declare (ignorable ,sym))
(flet ((f () ,sym))
(let ((,sym t))
(declare (ignorable ,sym))
(f))))))
(setq sym 'x)
(special? 'x) => NIL
(declaim (special x))
(special? 'x) => T
(unintern 'x)
(special? 'x) => NIL
(special? sym) => T
-- Robert
P. S. It is dangerous to proclaim a symbol to be globally special,
if its name does not begin and end with an asterisk. After I wrote
this article, I tried to connect to the Internet to post it, but
I couldn't because my dialing script was broken. Turns out the
dialing script uses a lexical variable named X, and this variable
was turned special (against its will) by a DECLAIM form that I had
evaluated while testing the code example you see above!
In article <DwuwC...@cogsci.ed.ac.uk>,
Jeff Dalton <je...@cogsci.ed.ac.uk> wrote:
> and it's odd that you regard this paragraph of yours as a summary.
> It certainly doesn't reflect the discussion *I've* seen.
I think Howard Stearns was just summarizing his own understanding
(which turned out to have resulted from misreading the compilation
environment rules in the wrong context).
He wasn't attempting to use the word in its more common Usenet
sense (a summary of all the discussion in a thread, or of just the
parts of the thread that have been accepted by all participants).
-- Robert
Lately nearly all of your words have been devoted to defending the
standard. That is pointless -- I am not challenging the standard,
nor is anyone else here. The problem is that your attacks on me
have not been consistent with the standard. Why aren't you trying
to defend your own articles, rather than the standard itself?
In article <30502106...@arcana.naggum.no>,
Erik Naggum <er...@naggum.no> wrote:
> such behavior reveals an amazingly cavalier attitude to
> reproducibility of observations
Reproducibility? In the last ten days you have reproduced against
me, in front of the whole world, the same kind of pointless abuse
that you must have waged against that other poor guy at some time
in the past. Apparently your behavior is VERY reproducible.
> you are in fact wrong on your technical points, Robert Munyer.
Present some evidence, please, or stop saying this.
Haven't you figured out yet that this is how you antagonize people?
You repeat (over and over, like a drone) "you are wrong" yet you
refuse to present evidence or answer legitimate questions. If this
had been a test in school, I would have had to give you an F,
because you never even filled in the blanks!
> and it is true, I do treat people who refuse to listen to
> authoritative sources and instead go on to ask _people_ what they
> think, as fundamentally misguided and extremely unlikely to
> produce anything of reasonable value in a discussion, because
> they discuss not what is, but what people believe.
I did not ask _people_ what they believe. I asked YOU what you
believe, because I was trying to figure out just exactly what it
is that you don't understand.
> you said you had a technical argument. I'll believe it when I
> see it.
I can't help you if you won't answer my questions. I have asked
you many explicit, specific questions in this thread and you have
evaded them. Go back and answer them, and then I'll be able to
help you clear up your confusion.
-- Robert
>> [...] (N.B. special but
>> not _proclaimed_ special, an important distinction. Special
>> proclamations make all bindings of the name special, declarations don't.)
>Based on those last two sentences I think you actually agree with
>me, not with Erik.
I do largely agree with you that globals are special/dynamic, but
I haven't found anything in the Standard that is as clear as
CLtL2 p 70. However, that doesn't seem to be the only issue ...
> Erik's latest attempt at spin control seems to
>be a claim that an implementation is allowed (under both CLtL2 and
>the ANSI standard) to PROCLAIM a symbol special, if you use SETQ
>to give it a global value. I'm not sure if Erik thinks this also
>applies to SET and SETF and (SETF SYMBOL-VALUE), because he refuses
>to answer my questions.
If the aim is to figure out the truth about Common Lisp, rather
than to win over particular individuals, then I don't think it
matters whether Eric has changed his position or not, or whatver
the "spin control" is about.
Anyway, I haven't looked into the question of whether implementations
can proclaim the variable special. I'd regard that as a hostile act
in most implementations, because it has a pervasive effect and there's
no way to undo it. (And if there is a way to undo it, it will be an
implementation-specific way.)
>Remember that in the HyperSpec, the unadorned term "variable" refers
>to a binding, not to the symbol that names the binding.
I haven't looked into it in detail, but I'd be careful about
concluding that just because it's what the glossary says. In any
case, I don't confine my own use of "variable" to that definition.
> I am not
>saying that a BINDING can be something other than lexical or constant
>or dynamic; I am saying that a NAME can have a lexical binding and
>a dynamic binding at the same time --
That much is clearly true; moreover, you should be able to refer
to both. For instance:
>(let ((x 1))
(declare (special x))
(let ((x 2))
(list (locally (declare (special x)) x)
x)))
(1 2)
If you put in special declarations, then I think the Standard is
clear, and you can get the "special but not proclaimed special"
behaviour for global variables. But without the declarations, what
are implementations allowed to do? That's not so clear, and you have
to look at lots of stuff: what are conforming implementations allowed
to do in various circumstances, and so on.
>That and in fact, that dynamic
>binding can be global. If you assign a global value to a variable
>name without proclaiming that name to be special, then you can
>still have lexical bindings on that same variable name.
Also true, even in CMUCL:
* (locally (declare (special snib)) (setq snib 10))
10
* (defun sx ()
(locally (declare (special snib)) snib))
sx
* (let ((snib 30)) (sx))
In: let ((snib 30))
(let ((snib 30))
(sx))
Warning: Variable snib defined but never used.
10
In CMU CL 17f, I get:
These proclaim special:
defparameter
defvar
setf
setq
These do not:
set
(setf symbol-value)
>In fact, since you've used over a dozen Common Lisps, you probably
>have several of them handy. It would be great if you could evaluate
>the above code in each of them.
I have only a few of them handy these days. However, both GCL-1.1
and Lucid 4.1 give the result you think they should.
>Also, any implementation which follows Erik's suggestion, and
>proclaims symbols special when not explicitly required to by the
>standard, will be unable to evaluate standard example code
>successfully. For example, see the code in the section on EVAL:
>
> http://www.harlequin.com/books/HyperSpec/Body/fun_eval.html
Good point. But I'm not sure examples really count -- I'd have
to find what the Spec says about the status of examples.
>> For instance, from PROCLAIM-LEXICAL version 2:
>
>This PROCLAIM-LEXICAL document to which you refer is very interesting.
>This is the first time I've heard that anyone on the committee has
>addressed this issue directly. PROCLAIM-LEXICAL is not mentioned
>in the standard; does that mean the issue never came to a vote?
It came to a vote; no proposals passed (or at least not any
that changed anything). But since this message is already long,
and since I'm out of time, I'll respond to your comments on
PROCLAIM-LEXICAL in a separate message later on. Meanwhile,
I've put some things on the Web that you may find of interest.
See http://www.aiai.ed.ac.uk/~jeff/lisp/special.html
-- jd
I didn't see all of the earlier discussion, for various reasons.
Could you perhaps say, for me and any others in similar boats,
what technical issue is, as you see it. Is it whether globals
are special, whether CMU CL is allowed to automatically proclaim
variables special, or something else?
>you are in fact wrong on your technical points, Robert Munyer. there is
>nothing more than "read the fine manual" to tell you. since you refuse to
>do that,
Well, I'll read the manual, if you say what sections you think
are relevant.
Unfortunately, my understanding of CL is not based on the Standard
but on CLtL I and what happened in X3J13. I assume the Standard
reflects the intentions of X3J13 (and that I understand those
intentions fairly well), but when it comes to the standard I
can seldom find all the relavant sections without a lot of mousing
around in the HyperSpec, so it's fairly easy for me to miss something.
-- jd
| Could you perhaps say, for me and any others in similar boats, what
| technical issue is, as you see it.
the initial technical point I made was that Common Lisp does not make the
distinction that Robert Munyer said it does in his reply, namely of
_treating_ foo special in (defvar foo ...) and _not_ special in (setq foo
...) at top-level. his exact words from <4v7ifq$9...@Mars.mcs.com> were as
follows:
DEFVAR doesn't just define a global variable X; it also declares
that all variables X are "special." A special variable is dynamic
rather than lexical, so it bypasses the normal scoping rule. Look
what would happen if you used SETQ rather than DEFVAR, to establish
a global variable without declaring it to be special:
? (setq x 100)
100
? (let ((x 1)) (eval 'x))
;Compiler warnings :
; Unused lexical variable X, in an anonymous lambda form.
100
I pointed out that the semantics of SETQ at top-level without a special
declaration is not defined by the language. and the fact remains, it is
not defined by the language. implementations are free to do what they
want.
| Well, I'll read the manual, if you say what sections you think are
| relevant.
in my reply to him in <30493952...@arcana.naggum.no>, I wrote:
for more information on the environments in Common Lisp, see the Common
Lisp Hyperspec at Harlequin, Inc, section 3.1.1 Introduction to
Environments.
http://www.harlequin.com/books/HyperSpec/Body/sec_3-1-1.html
after which Robert argued that the HyperSpec was in conflict with CLtL2,
that he could change a few words to amend his article, and strongly implied
that his purpose was to have _me_ (not the standard, not the language)
distinguish between the behavior of SETQ and DEFVAR at top-level, which I
had already stated very clearly was not defined by the standard.
res ipsa loquitur.
#\Erik
--
main () { printf ("%d\n", sin ("foo")); }
I have three quick arguments against the above conclusion. Taken
together, I believe they are conclusive and indisputable.
* Claim 1. Use of top-level SETQ to initialize a variable that
has not been previously declared special is completely acceptable
in a code example, even if it is not something you would do in
an actual program.
* Argument 1.1. This usage appears in the standard itself. For
example see the section on SETQ:
http://www.harlequin.com/books/HyperSpec/Body/spefor_setq.html
* Claim 2. It is not acceptable for an implementation to proclaim
a symbol special merely because its value is initialized by a
top-level SETQ.
* Argument 2.1. Such a proclamation would be a side effect.
The standard does not say that this side effect exists or
might exist. My understanding is that side effects are not
allowed unless the standard permits them explicitly.
If side effects were allowed whenever they are not explicitly
forbidden, all hell would break loose. Virtually any construct
could produce virtually any side effect, because the standard
very rarely states explicitly that a certain construct will
not have a certain side effect. Instead, it is taken for
granted that only documented side effects can exist.
* Argument 2.2. The standard itself contains code which (like
my own 8/18 example) would fail if this proclamation were
allowed to occur. Any implementation which produces this
undocumented side effect will fail to evaluate successfully
the following code example from the standard:
From the section on EVAL:
http://www.harlequin.com/books/HyperSpec/Body/fun_eval.html
(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
The standard example code above makes it absolutely clear
that SETQ does not, and must not, proclaim a symbol to be
special.
-- Robert
> [Jeff Dalton]
>
> | Could you perhaps say, for me and any others in similar boats,
> | what technical issue is, as you see it.
>
> the initial technical point I made was that Common Lisp does not
> make the distinction that Robert Munyer said it does in his reply,
> namely of _treating_ foo special in (defvar foo ...) and _not_
> special in (setq foo ...) at top-level.
What do you mean by "_treating_ foo special?" Do you mean (a)
proclaiming the symbol to be special? Or do you mean (b) placing
the new value in a binding that is special? If you answer (a), I
will rebut your answer. If you answer (b), I will agree with your
answer, but I will rebut any claim that it invalidates my 8/18 code
example which you just quoted on 8/30.
> in my reply to him in <30493952...@arcana.naggum.no>, I
> wrote:
>
> for more information on the environments in Common Lisp, see
> the Common Lisp Hyperspec at Harlequin, Inc, section 3.1.1
> Introduction to Environments.
>
> http://www.harlequin.com/books/HyperSpec/Body/sec_3-1-1.html
>
> after which Robert argued that the HyperSpec was in conflict with
> CLtL2,
Only in the details of how the word "variable" is defined, not in
the details of the technical question that we are discussing now.
> that he could change a few words to amend his article,
Again, because we were using subtly different definitions of the
word "variable." I amended the article to use the definition that
can be found in the glossary of the HyperSpec.
> and strongly implied that his purpose was to have _me_ (not the
> standard, not the language) distinguish between the behavior of
> SETQ and DEFVAR at top-level,
I did not imply any such thing.
-- Robert
> Anyway, I haven't looked into the question of whether implementations
> can proclaim the variable special. I'd regard that as a hostile
> act in most implementations, because it has a pervasive effect
> and there's no way to undo it. (And if there is a way to undo
> it, it will be an implementation-specific way.)
I agree. In fact I'd say this act is not only hostile, but incorrect.
> > The results should be:
> >
> > These proclaim special:
> > DEFPARAMETER
> > DEFVAR
> > These do not:
> > SET
> > SETF
> > (SETF SYMBOL-VALUE)
> > SETQ
>
> In CMU CL 17f, I get:
>
> These proclaim special:
> defparameter
> defvar
> setf
> setq
> These do not:
> set
> (setf symbol-value)
OK, then I can say unequivocally that CMU CL 17f has a bug (or else
it is not really standard Common Lisp). You used the word "hostile"
to describe exactly this feature of CMU CL 17f, right? I would go
further and use the word "incorrect" or "non-standard."
> > In fact, since you've used over a dozen Common Lisps, you
> > probably have several of them handy. It would be great if you
> > could evaluate the above code in each of them.
>
> I have only a few of them handy these days. However, both GCL-1.1
> and Lucid 4.1 give the result you think they should.
As does MCL (2.0.1 and 3.0).
> > Also, any implementation which follows Erik's suggestion, and
> > proclaims symbols special when not explicitly required to by the
> > standard, will be unable to evaluate standard example code
> > successfully. For example, see the code in the section on EVAL:
> >
> > http://www.harlequin.com/books/HyperSpec/Body/fun_eval.html
>
> Good point. But I'm not sure examples really count -- I'd have
> to find what the Spec says about the status of examples.
I certainly hope you don't find anything that says that examples
don't "really count." That would be awful. If the committee ever
said that everything written in English counts, and everything
written in Lisp does not, then they would be putting themselves in
the frightful position of having to define and describe a large
and complex programming language entirely in English.
English is fuzzy and imprecise; Lisp is not. If you read part of
the standard in English, and part of it in Lisp, and you think that
the English part says that the Lisp part is wrong, you had better
try to re-read the English part and see if there's another way you
could possibly interpret it.
In fact, I'd say that's exactly what code examples are for.
> Meanwhile, I've put some things on the Web that you may find of
> interest. See http://www.aiai.ed.ac.uk/~jeff/lisp/special.html
Excellent web page! Thank you for making it available (and telling
me about it).
Incidentally, David Moon's word "cell" corresponds very closely
with the way I used to like to use the word "variable," before I
found that doing so could cause so much confusion.
-- Robert
> * (let ((x 1)) (eval 'x))
> Warning: Variable X defined but never used.
> Error in KERNEL::UNBOUND-SYMBOL-ERROR-HANDLER:
> the variable X is unbound.
>
> This seems counterintuitive to me. Is EVAL just using the global
> environment? Is that what the language spec says it should be?
> If that is the case, how could the following behaviour be explained:
>
> * (defvar x 100)
> X
> * (let ((x 1)) (eval 'x))
> 1
> * x
> 100
>
> Note that the eval only seems to work after a *GLOBAL* variable
> 'x' has been defined.
Excerpted from Robert Munyer's 8/18 article <4v7ifq$9...@Mars.mcs.com>:
1> DEFVAR doesn't just define a global variable X; it also declares
2> that all variables X are "special." A special variable is dynamic
3> rather than lexical, so it bypasses the normal scoping rule. Look
4> what would happen if you used SETQ rather than DEFVAR, to establish
5> a global variable without declaring it to be special:
6>
7> ? (setq x 100)
8> 100
9> ? (let ((x 1)) (eval 'x))
A> ;Compiler warnings :
B> ; Unused lexical variable X, in an anonymous lambda form.
C> 100
On 8/19 I suggested changing "it" in line 5 above to "its name."
In this amended form, and using the definition of "variable" in
the HyperSpec's glossary, the above is correct and expresses the
idea that I meant to express.
But if I were answering Mr. Chan's question today, I would write
the answer differently so it would be less likely to be misunderstood.
I would replace the text in lines 1-5 with something like this:
DEFVAR doesn't just assign a global value to a symbol; it also
globally declares that symbol to be "special." This means that
from that point onward, all variable bindings and variable
references using that symbol will be "special," including for
example the binding created by your (LET ((X 1)) ...) form.
Special bindings and references are dynamic rather than lexical,
so they bypass the normal scoping rule. Look what would happen
if you used SETQ rather than DEFVAR, to assign 100 as the global
value of X without globally declaring the symbol X to be special:
I would also add a postscript to explain the problem with CMU CL.
Something like this:
P. S. At least one implementation (a version of CMU CL) has
a non-standard implementation of SETQ and will not produce the
correct result in that last example. You can work around the
problem in a number of ways. In standard Common Lisp you could
use any one of these six forms in that last example:
1. (setq x 100)
2. (setf x 100)
3. (set 'x 100)
4. (setf (symbol-value 'x) 100)
5. (locally (declare (special x)) (setq x 100))
6. (locally (declare (special x)) (setf x 100))
But in at least one version of CMU CL, you could not use #1 or
#2 and would have to choose one of #3 through #6.
-- Robert
There are problems with how RM's point was worded above, but I think
some of the things he said later made it clearer what he was getting
at. And he's at least partly right. (DEFVAR X ...) proclaims X
special, which affects all uses (reference, assignment, binding) of X
as a variable -- the `all variables X are "special"' above -- and
you can avoid this pervasive effect by not using DEFVAR.
>I pointed out that the semantics of SETQ at top-level without a special
>declaration is not defined by the language. and the fact remains, it is
>not defined by the language. implementations are free to do what they
>want.
Could you say _why_ you think the semantics is not defined and why
that leaves implementations free to do whatever they want? For
instance, if the standard explicitly said "the consquences are
undefined", or used one of the other phrases defined in the dection
on error terminology, that would make things fairly clear.
But it looks instead like (at most) the standard merely fails to state
the semantics, and I don't know where it says what implementations can
do in such cases.
There are also a number of things in the standard that suggest that
the semantics of top-level SETQ is defined, so that any failure
to explicitly and clearly define it is an oversight. (I've discussed
some of these in earlier articles and won't repeat the discussion
here.)
(Note for RM: the standard explicitly says that "Examples"
sections are not part of the standard.)
-- jd