In article <33Dr4.39317$632.1701...@news1.rdc2.on.home.com>,
Tyler Durden <maxqpo...@hotmail.com> wrote: > So, would > (defun fact (x) (cond ((<= x 0) 1) ('t (* x (fact (1- x)))))) > (setq x 7) > (fact 3) > return a stack overflow because of repeated calls to (fact 6)?
No, that version of FACT will work in a lexically scoped Lisp or a dynamically scoped one. The code inside the function will use the appropriate inner binding of X, not the outer binding X = 7.
FOO is different, because it uses EVAL. In Common Lisp, FOO's binding of X is lexical by default, and can't be accessed by the code that's evaluated by EVAL. That's why, as [previous author] said, 5 is correct in Common Lisp.
You can also get Common Lisp to do dynamic binding, just like those older lisps, by declaring a variable to be "special." Note: it's been reported that at least one CL implementation will implicitly declare all uses of X to be special, including the ones in FOO, when it sees your (SETQ X 3) at the top level. Doing it that way is a "bad idea," and I hope the situation has been corrected by now. If that implementation used a compiler, I suspect that it would correctly return 5 the first time you tried your code above, but then if you ever re-evaluated the DEFUN form again after evaluating the SETQ, from then on the compiler would compile FOO incorrectly, and then (FOO '(+ X 2)) would result in an error.
P. S. A couple of years ago I had an exasperating flame war with Erik over a question very similar to this one. I eventually won the war, by finding an excerpt from the HyperSpec that demonstrated the exact opposite of Erik's main technical argument.
But it was a Pyrrhic victory. Trying to have a technical debate with Erik was so incredibly time-consuming and unproductive, and so unpleasant in general, that as soon as I finished winning the debate, I stopped reading this newsgroup for more than a year.
My advice to anyone who finds himself in a dispute with Erik: resist the temptation to flame back. Do not try to respond (not even in self defense) to the non-technical personal attacks. If you must respond, limit your response to a statement like "That's an inappropriate personal attack, and I won't dignify it with a response." If you allow your debate to turn into a war of personal attacks, it will waste a lot of bandwidth -- and I guarantee that you won't enjoy the debate, even if you win it. (Unless you're deliberately trolling for conflict, like the schizophrenic Perl programmer who's been posting here lately!)
* Robert Munyer <mun...@mcs.com> | P.S. A couple of years ago I had an exasperating flame war with Erik | over a question very similar to this one. I eventually won the war, by | finding an excerpt from the HyperSpec that demonstrated the exact | opposite of Erik's main technical argument.
August 1996. I think comp.lang.lisp readers deserve the opportunity to read the discussion for themselves, not the least to understand why Robert's self-serving summary is _still_ his position, and why it is still important that he be shot down, because he's _still_ wrong, nearly four years later.
the following "power search" line lists them from www.deja.com:
the original question was why (let ((x 10)) (eval 'x)) produces different results before and after a special declaration of x. this stumps newbies at times, but it can be explained easily and well unless you get it wrong.
so the problem with that debate was that Robert insisted on bringing up a *huge* number of *tiny* arguments. Robert _did_ field a war over quibbly little details, while everybody else were either trying to unconfuse him, calm him down, or putting in their earplugs. naturally, winning this war meant nobody made the effort to respond to more of the same old rants.
my _main_ argument was that Common Lisp doesn't have a concept of "global variables", but lexical and dynamic _bindings_, and lexical and global symbol _references_ (explained in various bits and pieces -- the whole discussion helped clarify the issues for me). Robert's main point was that you could have a lexical and a dynamic variable with the same name. he's right (and I _never_ disagreed with him on it, because it is wholly irrelevant): the latter is called the symbol-value of a symbol that has _not_ been declared special, because a reference to a variable that is not lexical is identical to symbol-value of the symbol naming it. as most confused people who are right, Robert was right for wrong reasons: he didn't understand the distinction between binding and references to variables. apparently, he learned nothing from the whole exercise.
here's an excerpt I think highlights exactly why Robert is _still_ upset:
> (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.
I clearly fell short of his expectations. of course that's _my_ fault.
incidentally, Robert's parting words to us were as follows:
The standard example code above makes it absolutely clear that SETQ does not, and must not, proclaim a symbol to be special.
no wonder it didn't really feel good to part on this winning note: it's not a winning note. it's an admission of not remembering from early warnings in the same discussion that examples are not even considered part of the standard, for the very simple reason that the requirements have to be _uniquely_ authoritative.
so the "excerpt from the HyperSpec that demonstrates the exact opposite of Erik's main technical point" is simply a lie -- but it's the kind you win wars with, because people normally let you think you won when you say something sufficiently stupid and gloat and brag about it to boot.
I have a proposal to put to the group. We organise a fund to fly me to wherever these two hang out, armed with my trusty ruler.
Once I return here I can email the group with the information about exactly who has the larger penis and so settle the dispute beyond all doubt.
Andrew
In article <3160252167384...@naggum.no>, Erik Naggum <e...@naggum.no> wrote:
> * Robert Munyer <mun...@mcs.com> > | P.S. A couple of years ago I had an exasperating flame war with Erik > | over a question very similar to this one. I eventually won the war, by > | finding an excerpt from the HyperSpec that demonstrated the exact > | opposite of Erik's main technical argument.
> August 1996. I think comp.lang.lisp readers deserve the opportunity to > read the discussion for themselves, not the least to understand why > Robert's self-serving summary is _still_ his position, and why it is > still important that he be shot down, because he's _still_ wrong, nearly > four years later.
In article <3160252167384...@naggum.no>, Erik Naggum wrote: > my _main_ argument was that Common Lisp doesn't have a concept of "global > variables", but lexical and dynamic _bindings_, and lexical and global > symbol _references_ (explained in various bits and pieces -- the whole > discussion helped clarify the issues for me). Robert's main point was > that you could have a lexical and a dynamic variable with the same name. > he's right (and I _never_ disagreed with him on it, because it is wholly > irrelevant): the latter is called the symbol-value of a symbol that has > _not_ been declared special, because a reference to a variable that is > not lexical is identical to symbol-value of the symbol naming it. as > most confused people who are right, Robert was right for wrong reasons: > he didn't understand the distinction between binding and references to > variables.
Could you explain the distinction? I've read the 1996 thread but could not figure that out.
* Keke Abe | Could you explain the distinction? I've read the 1996 thread but could | not figure that out.
a binding of a lexical variable is an entirely new variable, one that may be captured independently of any other variable, and which is not visible anywhere else. a binding of a special variable is a dynamic association between variable and value which is seen everywhere else the same variable is referenced. the reference to a lexical variable is under the supreme control of the compiler, which may allocate it to a register or to a stack frame, and which will typically discard the symbol association. the reference to a special variable is like a call to symbol-value on that symbol.
this means that the statement "there may be a lexical and dynamic variable with the same name" is terribly confused. yes, it is possible to "forget" to declare a symbol special, which means any binding will be lexical, but so, then, will any normal reference. in order to access the symbol, you can no longer just name it, you need to call symbol-value or set when you want to read or change its value. but at this time, we're clearly doing something very different than what we did with variables -- we're actually tinkering with the underlying implementation of special variables.
a fully true statement would be that the symbol-value slot of a symbol is accessible and may be accessed also when the symbol has not been declared special. however, using a variable means _not_ having to do anything special like that at every access, so it's clear that we access a symbol's internal information in code like this:
(1) common-lisp-user ;; In Lisp Listener #2 (2) common-lisp-user (defun foobar (x) (values x (symbol-value 'x))) => foobar (3) common-lisp-user (setq x 666) => 666 (4) common-lisp-user (foobar 4711) => 4711 => 666 (5) common-lisp-user (defvar x 69) => x (6) common-lisp-user (foobar 4711) => 4711 => 4711 (7) common-lisp-user
It takes a pretty smart implementation of Common Lisp to actually produce this result as presented. In most systems you'll have to recompile FOOBAR after DEFVARing X to see the result:
? (defun foo (x) (values x (symbol-value 'x))) FOO ? (setf x 666) 666 ? (foo 4711) 4711 666 ? (defvar x 69) X ? (foo 4711) 4711 69 ? (defun foo (x) (values x (symbol-value 'x))) FOO ? (foo 4711) 4711 4711 ?
g...@jpl.nasa.gov (Erann Gat) writes: > It takes a pretty smart implementation of Common Lisp to actually > produce this result as presented.
Not really. GCL produces the result just as Erik gave it.
> In most systems you'll have to > recompile FOOBAR after DEFVARing X to see the result:
I suspect that most systems still use an interpreter for the read-eval-print loop, and most of them will work as Erik suggested.
Other issues:
1. I don't think there's anything especially confused about saying there can be a lexical and a dymamic variable of the same name. That there can be is why
(values x (locally (declare (special x)) x))
can return two different values.
2. It's sometimes necessary to distinguish between declaring special (with DECLARE) and proclaiming special (with PROCLAIM or DECLAIM). DEFVAR proclaims the var special, and that makes it pervasively "special everywhere" - but merely declaring something special has only a local effect.
A further complication is the treatment of plain refs to "global" variables. They are refs to the special variable. That is, a free x, not declared or proclaimed special, and
(locally (declare (special x)) x)
refer to the same thing. [It's similar for assignment.]
3. CMUCL proclaims such "undeclared" free variables special automatically. So far as I know, no other implementation does that. They treat it as a ref to the special var and issue a warning, and usually don't bother to warn when interpreting rather than compiling.
So far as I can recall, having looked into this one of the times when it was an issue before, the ANSI standard does not explicitly forbid CMUCL's behaviour.
(CLtL was reasonably clear that such refs were refs to the special variable. The standard may not be so clear, and that may be what allows CMUCL's behaviour. I don't remember what the standard says well enough to say without spending a fair amount of time on it.)
In any case, I think CMUCL's behaviour should be forbidden, because the consequences of proclaiming a variable special are so extreme. Just because I type (setq x 100) to the top-level REPL doesn't mean I want x to be special wherever it's used. Sure, if I'd typed (setq *x* 100), having "forgotten" to defvar it, I might be happy if *x* were proclaimed special automatically. But that isn't what I typed.
These issues become clearer if you look at them from the point of view of someone who never wants to proclaim anything special. It becomes awkward to use "global" variables in that case, because compilers issue warnings, and CMUCL proclaims them special by default.
There was a cleanup issue, PROCLAIM-LEXICAL, that would have dealt with some of these issues, but it had consequences (such as lexical globals) that made enough people reluctant to adopt it.
> > It takes a pretty smart implementation of Common Lisp to actually > > produce this result as presented.
> Not really. GCL produces the result just as Erik gave it.
> > In most systems you'll have to > > recompile FOOBAR after DEFVARing X to see the result:
> I suspect that most systems still use an interpreter for the > read-eval-print loop, and most of them will work as Erik suggested.
Quite so. I've been using MCL for so long, where (EVAL X) == (FUNCALL (COMPILE (LAMBDA () X))) that I actually forgot about interpreted code. (You can imagine how exasperated I must get when people complain that Lisp is slow because it's interpreted.)
> Other issues:
> 1. I don't think there's anything especially confused about saying there > can be a lexical and a dymamic variable of the same name. That there > can be is why
> (values x > (locally (declare (special x)) > x))
> can return two different values.
Did you mean to write confused or confusing? If you meant confused then I agree with you. If you meant confusing then I disagree. The concept may not be confusing, but the explanations that are bandied about can be mightily confusing.
> There was a cleanup issue, PROCLAIM-LEXICAL, that would have dealt > with some of these issues, but it had consequences (such as lexical > globals) that made enough people reluctant to adopt it.
Here's an idea: define a reader macro for $ that expands into SYMBOL-VALUE. That would give the following behavior:
(setf x 0) at top level --> error or warning (assignment to non-existant lexical binding, or assuming dynamic binding is intended and assigning to $x instead)
Now extend the lambda-list syntax to allow variables with names that are lists beginning with SYMBOL-VALUE, kind of like extending the syntax of function names to allow names that are lists beginning with SETF. So instead of:
(lambda (x y) (declare (special y)) (values x y))
you now write:
(lambda (x $y) (values x $y))
In fact, you can now have a lexical and a dynamic binding of a variable with the same name in the same lambda expression:
(lambda (x $x) (values x $x))
X is always lexical. $X is always dynamic.
This proposal has many advantages:
1. It's backwards-compatible with the existing standard, and provides a path for deprecating (declare (special ...)) and all the related gunk.
2. It enforces a lexically apparent distinction between references to lexical and dynamic bindings, kind of like the *...* convention now in common use. The convention is also compatible with common practice in the non-Lisp world, which should help non-Lispers feel a little warmer and fuzzier when transitioning to Lisp.
3. It requires only minimal changes to existing compilers: add a reader macro, and change the lambda-list processing routines to translate
* g...@jpl.nasa.gov (Erann Gat) | It takes a pretty smart implementation of Common Lisp to actually | produce this result as presented. In most systems you'll have to | recompile FOOBAR after DEFVARing X to see the result:
foo was never compiled. there are downsides to compile-only systems.