From: Mattias Nilsson
Subject: Closures in CLISP. (Newbie question)
Date: 
Message-ID: <1132523793.551350.270490@o13g2000cwo.googlegroups.com>
Hi everybody,

I am yet another new CL learner, and I have a question that I suspect
is implementation related. However, since I am not yet thinking in CL,
I thought I should ask here just to be sure.

On p.18 in Graham's "On Lisp" I found the following introductory
example of closure:

(let ((counter 0))
  (defun new-id () (incf counter))
  (defun reset-id () (setq counter 0)))

The way I think I understand closures, there should be no way
of tampering with the value of counter as used by the two closures
in the lines above, except by evaluating the forms (new-id) and
(reset-id).

However, when I later do (defparameter counter 17) in
CLISP (v. 2.34), (new-id) next evaluates to 18. Then, if I do
(makunbound 'counter), the closures refuse to work.

I tried the same thing in SBCL (v. 0.9.4), and there it worked more
like I guessed it would; no matter what I do to counter in the
top-level, the closures continue to do their work.

Bottom line: Is there some point I have misunderstood, or is there
something fishy with CLISP (2.34)?

Best regards,
Mattias Nilsson,
Lispnik wannabe.

From: Sam Steingold
Subject: Re: Closures in CLISP. (Newbie question)
Date: 
Message-ID: <uoe4erihw.fsf@gnu.org>
> * Mattias Nilsson <········@oerqonaq.arg> [2005-11-20 13:56:33 -0800]:
>
> (let ((counter 0))
>   (defun new-id () (incf counter))
>   (defun reset-id () (setq counter 0)))
>
> The way I think I understand closures, there should be no way
> of tampering with the value of counter as used by the two closures
> in the lines above, except by evaluating the forms (new-id) and
> (reset-id).
>
> However, when I later do (defparameter counter 17) in
> CLISP (v. 2.34), (new-id) next evaluates to 18. Then, if I do
> (makunbound 'counter), the closures refuse to work.

Edi has explained everything quite correctly.
if you do

(let ((counter 0))
  (declare (compile)) ; http://clisp.cons.org/impnotes/declarations.html#compile-decl
  (defun new-id () (incf counter))
  (defun reset-id () (setq counter 0)))

you will not observe this behavior.

the problem is that the interpreted code is interpreted every time you
evaluate it, so when you change the global environment (by
defparameter), you get different interpretation of the code.



-- 
Sam Steingold (http://www.podval.org/~sds) running w2k
http://www.openvotingconsortium.org/ http://www.palestinefacts.org/
http://pmw.org.il/ http://www.honestreporting.com http://www.iris.org.il
Vegetarians eat Vegetables, Humanitarians are scary.
From: David Trudgett
Subject: Re: Closures in CLISP. (Newbie question)
Date: 
Message-ID: <m3y83i9rga.fsf@rr.trudgett>
Sam Steingold <···@gnu.org> writes:

>> * Mattias Nilsson <········@oerqonaq.arg> [2005-11-20 13:56:33 -0800]:
>>
>> (let ((counter 0))
>>   (defun new-id () (incf counter))
>>   (defun reset-id () (setq counter 0)))
>>
>> The way I think I understand closures, there should be no way
>> of tampering with the value of counter as used by the two closures
>> in the lines above, except by evaluating the forms (new-id) and
>> (reset-id).
>>
>> However, when I later do (defparameter counter 17) in
>> CLISP (v. 2.34), (new-id) next evaluates to 18. Then, if I do
>> (makunbound 'counter), the closures refuse to work.
>
> Edi has explained everything quite correctly.
> if you do
>
> (let ((counter 0))
>   (declare (compile)) ; 
>   (defun new-id () (incf counter))
>   (defun reset-id () (setq counter 0)))
>
> you will not observe this behavior.
>
> the problem is that the interpreted code is interpreted every time you
> evaluate it, so when you change the global environment (by
> defparameter), you get different interpretation of the code.
>

I just read that section yesterday, and ran that example through SLIME
and CMUCL! How about that?

It seems to me, also as a Lisp newcomer, by the way, that the clisp
result is incorrect because COUNTER is lexically scoped, no matter
whether it is in interpreted or compiled code. For proof, I can only
offer the interpreted results of CMUCL:

CL-USER> (let ((counter 0))
   (defun new-id () (incf counter))
   (defun reset-id () (setq counter 0)))
; Converted NEW-ID.
; Converted RESET-ID.
RESET-ID
CL-USER> (new-id)
1
CL-USER> (defparameter counter 4)
COUNTER
CL-USER> (new-id)
2
CL-USER> #'new-id
#<Interpreted Function NEW-ID {584B6159}>
CL-USER> 


Cheers,

David



-- 

David Trudgett
http://www.zeta.org.au/~wpower/

Problems cannot be solved 
at the same level of awareness 
that created them.

    -- Albert Einstein
From: Christophe Rhodes
Subject: Re: Closures in CLISP. (Newbie question)
Date: 
Message-ID: <sqr79a8cjt.fsf@cam.ac.uk>
David Trudgett <······@zeta.org.au.nospamplease> writes:

> It seems to me, also as a Lisp newcomer, by the way, that the clisp
> result is incorrect because COUNTER is lexically scoped, no matter
> whether it is in interpreted or compiled code. For proof, I can only
> offer the interpreted results of CMUCL:

That's not terribly good proof...

> CL-USER> (let ((counter 0))
>    (defun new-id () (incf counter))
>    (defun reset-id () (setq counter 0)))
> ; Converted NEW-ID.
> ; Converted RESET-ID.
> RESET-ID
> CL-USER> (new-id)
> 1
> CL-USER> (defparameter counter 4)
> COUNTER
> CL-USER> (new-id)
> 2
> CL-USER> #'new-id
> #<Interpreted Function NEW-ID {584B6159}>
> CL-USER> 

You might be interested in the answer to 
  (compiled-function-p #'new-id)
in CMUCL.

(This happens because, although #'new-id in this case is not compiled
to native code, it is "minimally compiled" in the standard sense[*]:
CMUCL does not interpret the code directly, but instead interprets a
high-level compiler representation of the code).

Christophe

[*] CLHS 3.2.2.2
From: David Trudgett
Subject: Re: Closures in CLISP. (Newbie question)
Date: 
Message-ID: <m3acfxlkd3.fsf@rr.trudgett>
Christophe Rhodes <·····@cam.ac.uk> writes:

> David Trudgett <······@zeta.org.au.nospamplease> writes:
>
>> It seems to me, also as a Lisp newcomer, by the way, that the clisp
>> result is incorrect because COUNTER is lexically scoped, no matter
>> whether it is in interpreted or compiled code. For proof, I can only
>> offer the interpreted results of CMUCL:
>
> That's not terribly good proof...

Well, it's an imperfect world, Christophe! ;-)


>
>> CL-USER> (let ((counter 0))
>>    (defun new-id () (incf counter))
>>    (defun reset-id () (setq counter 0)))
>> ; Converted NEW-ID.
>> ; Converted RESET-ID.
>> RESET-ID
>> CL-USER> (new-id)
>> 1
>> CL-USER> (defparameter counter 4)
>> COUNTER
>> CL-USER> (new-id)
>> 2
>> CL-USER> #'new-id
>> #<Interpreted Function NEW-ID {584B6159}>
>> CL-USER> 
>
> You might be interested in the answer to 
>   (compiled-function-p #'new-id)
> in CMUCL.

Let me guess... T? The old compiled interpreted code trick, eh?


>
> (This happens because, although #'new-id in this case is not compiled
> to native code, it is "minimally compiled" in the standard sense[*]:
> CMUCL does not interpret the code directly, but instead interprets a
> high-level compiler representation of the code).

So, there is more than one meaning of "interpreted", then, is what you
mean to say.

It still seems to me that CMUCL got it right in this case, and clisp
got it wrong. Unless I am mistaken, lexical scoping is a fundamental
attribute of Common Lisp, and one of the things that sets it apart
from the older dynamically scoped lisps. Take away lexical scoping (as
in the clisp interpreted example) and you don't have Common Lisp.

So, there are two possibilities that I can think of right now:

1. clisp is not behaving as a correct CL implementation in this instance.

or

2. The CL spec itself allows implementations to take or leave lexical
   scoping as they see fit.


Neither of those possibilities is good, in my opinion.


David



-- 

David Trudgett
http://www.zeta.org.au/~wpower/

The whole system of domination might unravel if the idea of taking
matters into one's own hands spreads its evil tentacles.

    -- Noam Chomsky
       <http://www.chomsky.info/articles/20041217.htm>
From: Sam Steingold
Subject: Re: Closures in CLISP. (Newbie question)
Date: 
Message-ID: <u8xvhpqko.fsf@gnu.org>
> * David Trudgett <······@mrgn.bet.nh.abfcnzcyrnfr> [2005-11-22 09:14:00 +1100]:
>
>> (This happens because, although #'new-id in this case is not compiled
>> to native code, it is "minimally compiled" in the standard sense[*]:
>> CMUCL does not interpret the code directly, but instead interprets a
>> high-level compiler representation of the code).
>
> So, there is more than one meaning of "interpreted", then, is what you
> mean to say.

no, the notion of a "interpreted function" has 1 meaning.
http://www.lisp.org/HyperSpec/Body/glo_i.html#interpreted_function

> It still seems to me that CMUCL got it right in this case, and clisp
> got it wrong. Unless I am mistaken, lexical scoping is a fundamental
> attribute of Common Lisp, and one of the things that sets it apart
> from the older dynamically scoped lisps. Take away lexical scoping (as
> in the clisp interpreted example) and you don't have Common Lisp.

CLISP does not take the lexical scoping away.  if the user is crazy
enough to use the same symbol for lexical variables in some places and
for global special variables in other places, he can still get what he
wants by compiling the forms that use the symbol as a lexical variable
before declaring the symbol global special.

the rationale for CLISP behavior is to ease interactive development.
clisp merely allows the user not to re-evaluate his definitions if she
all of a sudden decides that some variables should be special and not
lexical (e.g., to simplify debugging), or if she just forgot to type
(defvar *foo*) until she typed 20 forms that use *foo* - these 20 forms
will have to be re-typed under CMUCL but not under CLISP.


> 1. clisp is not behaving as a correct CL implementation in this instance.

CLISP is 100% conforming in this specific issue.
CLISP includes an "interpreted implementation" (in addition to a
"compiled implementation")
http://www.lisp.org/HyperSpec/Body/glo_i.html#interpreted_implementation:
        interpreted implementation n. an implementation that uses an
        execution strategy for interpreted functions that does not
        involve a one-time semantic analysis pre-pass, and instead uses
        ``lazy'' (and sometimes repetitious) semantic analysis of forms
        as they are encountered during execution.

this means that when you type

#1=(let ((foo 10)) (defun bar () ... foo ...))
(bar)

the form #2# is analyzed and interpreted and FOO is a lexical variable
in BAR.  when you later type

(defvar foo 11)
(bar)

the form #2# is analyzed and interpreted _again_ and FOO is now a
special variable in BAR.


summary:

1. CLISP is conforming

2. CLISP behavior is useful under some circumstances (just like the
   CMUCL behavior -- also conforming! -- is useful under some _other_
   circumstances).

3. using a naming convention that clearly separates special and lexical
   variable names is a good idea.

-- 
Sam Steingold (http://www.podval.org/~sds) running w2k
http://www.palestinefacts.org/ http://truepeace.org http://www.iris.org.il
http://www.honestreporting.com http://ffii.org/ http://www.mideasttruth.com/
I don't want to be young again, I just don't want to get any older.
From: Mattias Nilsson
Subject: Re: Closures in CLISP. (Newbie question)
Date: 
Message-ID: <1132656380.833063.44980@g14g2000cwa.googlegroups.com>
Sam Steingold wrote:

> the rationale for CLISP behavior is to ease interactive development.
> clisp merely allows the user not to re-evaluate his definitions if she
> all of a sudden decides that some variables should be special and not
> lexical (e.g., to simplify debugging), or if she just forgot to type
> (defvar *foo*) until she typed 20 forms that use *foo* - these 20 forms
> will have to be re-typed under CMUCL but not under CLISP.

Makes sense.

> summary:
>
> 1. CLISP is conforming
>
> 2. CLISP behavior is useful under some circumstances (just like the
>    CMUCL behavior -- also conforming! -- is useful under some _other_
>    circumstances).
>
> 3. using a naming convention that clearly separates special and lexical
>    variable names is a good idea.

Got it! I guess my original confusion was caused by the fact that the
example in the book ("On Lisp") was not presented in a context
mentioning the mode of evaluation. Well, I will try to be a bit more
careful from now on...

Regards,
Mattias.
From: David Trudgett
Subject: Re: Closures in CLISP. (Newbie question)
Date: 
Message-ID: <m3irukwbpf.fsf@rr.trudgett>
Hi Sam,

Thanks for the more in-depth explanation. What you seem to be saying
is that CLISP took a pragmatic approach to facilitate some styles of
interactive development at the REPL, and for this reason decided to
allow special variables to hide lexical ones (to allow developers to
change their mind, or make debugging easier), or to put it another
way, to allow dynamic binding to override lexical binding. I can
certainly understand that point of view.

Speaking for myself, though, and the relatively little Common Lisp
development I have done, I don't actually type away at the REPL in the
manner you seem to be hinting at. Of course, we all type things at the
REPL for testing and debugging purposes, but I don't type all my
functions and definitions in at the REPL during the development
process because that is just a recipe for losing all or part of
it. Instead, and I tend to believe this is the common way to do it, I
enter my code into a text editor buffer, saving as I see fit, and send
definitions across to lisp as I complete them. A couple of keystrokes
and I can also reload the entire source file, if necessary.


Sam Steingold <···@gnu.org> writes:

>> * David Trudgett <······@mrgn.bet.nh.abfcnzcyrnfr> [2005-11-22 09:14:00 +1100]:
>
>> It still seems to me that CMUCL got it right in this case, and clisp
>> got it wrong. Unless I am mistaken, lexical scoping is a fundamental
>> attribute of Common Lisp, and one of the things that sets it apart
>> from the older dynamically scoped lisps. Take away lexical scoping (as
>> in the clisp interpreted example) and you don't have Common Lisp.
>
> CLISP does not take the lexical scoping away.  

In a literal minded sense, you are right, of course. All it does is
allow dynamic binding to override lexical binding, for the pragmatic
reasons you mentioned. This is not normally a problem, though, for
those who follow the sensible course of naming special variables with
asterisks.



> if the user is crazy enough to use the same symbol for lexical
> variables in some places and for global special variables in other
> places, 

It's true that this practice is probably a crazy one. On the other
hand, I am loathe to make any such a priori judgements because we are
not gods and the programmer must decide in any particular unique
situation what is the best thing to do. 

As a bit of a digression, it's a bit like laws in the wider world,
really. One of the great inherent problems with them is that they set
themselves up as gods to pronounce what is good for all people at all
times. Life isn't as simple as such control-paradigm-based thinking
would have it.



> he can still get what he wants by compiling the forms that use the
> symbol as a lexical variable before declaring the symbol global
> special.
>
> the rationale for CLISP behavior is to ease interactive development.
> clisp merely allows the user not to re-evaluate his definitions if
> she all of a sudden decides that some variables should be special
> and not lexical (e.g., to simplify debugging), or if she just forgot
> to type (defvar *foo*) until she typed 20 forms that use *foo* -
> these 20 forms will have to be re-typed under CMUCL but not under
> CLISP.
>
>
>> 1. clisp is not behaving as a correct CL implementation in this
>> instance.
>
> CLISP is 100% conforming in this specific issue.
> CLISP includes an "interpreted implementation" (in addition to a
> "compiled implementation")
> http://www.lisp.org/HyperSpec/Body/glo_i.html#interpreted_implementation:
>         interpreted implementation n. an implementation that uses an
>         execution strategy for interpreted functions that does not
>         involve a one-time semantic analysis pre-pass, and instead uses
>         ``lazy'' (and sometimes repetitious) semantic analysis of forms
>         as they are encountered during execution.
>
> this means that when you type
>
> #1=(let ((foo 10)) (defun bar () ... foo ...))
> (bar)
>
> the form #2# is analyzed and interpreted and FOO is a lexical variable
> in BAR.  when you later type
>
> (defvar foo 11)
> (bar)
>
> the form #2# is analyzed and interpreted _again_ and FOO is now a
> special variable in BAR.

Overriding or hiding the prior lexical binding... Does that conform to
the CL spec? You say it does, so I suppose you are right.


>
>
> summary:
>
> 1. CLISP is conforming
>
> 2. CLISP behavior is useful under some circumstances (just like the
>    CMUCL behavior -- also conforming! -- is useful under some _other_
>    circumstances).
>
> 3. using a naming convention that clearly separates special and lexical
>    variable names is a good idea.


Thanks for the further explanation, Sam. 

Bye for now,

David



-- 

David Trudgett
http://www.zeta.org.au/~wpower/

Perhaps we have reached a point in history that will separate the
decent from the indecent -- a time when the disconnect between the
agenda being pursued and the interests of the people has grown so
enormous that lies will only continue to sell the system to those who
want to be lied to.
    
    -- David McGowan, April 2003. 
       http://davesweb.cnchost.com/nwsltr34.html
From: Sam Steingold
Subject: Re: Closures in CLISP. (Newbie question)
Date: 
Message-ID: <uoe4cmfpm.fsf@gnu.org>
Hi David,

> * David Trudgett <······@mrgn.bet.nh.abfcnzcyrnfr> [2005-11-23 09:37:48 +1100]:
>
> I don't type all my functions and definitions in at the REPL during
> the development process ...  I enter my code into a text editor
> buffer, saving as I see fit, and send definitions across to lisp as I
> complete them. A couple of keystrokes and I can also reload the entire
> source file, if necessary.

of course.
if you send the definitions one by one, then the CLISP way saves you the
keystrokes to re-send the 20 definitions.
if you just reload the file (and you sensibly defvar your globals before
using them), then the CLISP does not win you anything.
note however that reloading the file is not something one can always
easily do in the middle of the development process: some definitions
may be incomplete or broken and you may not want to clobbers older
working versions with the newer broken ones.  the file might not even
load because of paren mismatch &c.

>> the form #2# is analyzed and interpreted _again_ and FOO is now a
>> special variable in BAR.
>
> Overriding or hiding the prior lexical binding... Does that conform to
> the CL spec? You say it does, so I suppose you are right.

there is no "prior lexical binding".
when you type (BAR) it is as if you re-typed its definition.

> Thanks for the further explanation, Sam. 
you are welcome.

-- 
Sam Steingold (http://www.podval.org/~sds) running w2k
http://www.mideasttruth.com/ http://www.honestreporting.com
http://www.memri.org/ http://pmw.org.il/ http://truepeace.org
Any programming language is at its best before it is implemented and used.
From: Pascal Bourguignon
Subject: Re: Closures in CLISP. (Newbie question)
Date: 
Message-ID: <87u0e4utm6.fsf@thalassa.informatimago.com>
David Trudgett <······@zeta.org.au.nospamplease> writes:

> Hi Sam,
>
> Thanks for the more in-depth explanation. What you seem to be saying
> is that CLISP took a pragmatic approach to facilitate some styles of
> interactive development at the REPL, and for this reason decided to
> allow special variables to hide lexical ones (to allow developers to
> change their mind, or make debugging easier), or to put it another
> way, to allow dynamic binding to override lexical binding. I can
> certainly understand that point of view.
>
> Speaking for myself, though, and the relatively little Common Lisp
> development I have done, I don't actually type away at the REPL in the
> manner you seem to be hinting at. Of course, we all type things at the
> REPL for testing and debugging purposes, but I don't type all my
> functions and definitions in at the REPL during the development
> process because that is just a recipe for losing all or part of
> it. 

If you use slime, you might be using the REPL a lot without noticing.

> Instead, and I tend to believe this is the common way to do it, I
> enter my code into a text editor buffer, saving as I see fit, and send
> definitions across to lisp as I complete them. A couple of keystrokes
> and I can also reload the entire source file, if necessary.

-- 
"You question the worthiness of my code? I should kill you where you
stand!"
From: Edi Weitz
Subject: Re: Closures in CLISP. (Newbie question)
Date: 
Message-ID: <ufyprm0gi.fsf@agharta.de>
On 20 Nov 2005 13:56:33 -0800, "Mattias Nilsson" <········@bredband.net> wrote:

> I am yet another new CL learner, and I have a question that I
> suspect is implementation related. However, since I am not yet
> thinking in CL, I thought I should ask here just to be sure.
>
> On p.18 in Graham's "On Lisp" I found the following introductory
> example of closure:
>
> (let ((counter 0))
>   (defun new-id () (incf counter))
>   (defun reset-id () (setq counter 0)))
>
> The way I think I understand closures, there should be no way of
> tampering with the value of counter as used by the two closures in
> the lines above, except by evaluating the forms (new-id) and
> (reset-id).
>
> However, when I later do (defparameter counter 17) in CLISP
> (v. 2.34), (new-id) next evaluates to 18. Then, if I do (makunbound
> 'counter), the closures refuse to work.
>
> I tried the same thing in SBCL (v. 0.9.4), and there it worked more
> like I guessed it would; no matter what I do to counter in the
> top-level, the closures continue to do their work.
>
> Bottom line: Is there some point I have misunderstood, or is there
> something fishy with CLISP (2.34)?

You're seeing the difference between interpreted and compiled code.
SBCL always compiles code while CLISP does it only on demand.  Try
compiling NEW-ID and RESET-ID in CLISP before you enter your
DEFPARAMETER form (and thereby declare COUNTER to be globally
special).

See 3.2.2.3 in the standard where it says that

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

Cheers,
Edi.

-- 

Lisp is not dead, it just smells funny.

Real email: (replace (subseq ·········@agharta.de" 5) "edi")
From: Mattias Nilsson
Subject: Re: Closures in CLISP. (Newbie question)
Date: 
Message-ID: <1132525584.967283.112510@g43g2000cwa.googlegroups.com>
Edi Weitz wrote:

> You're seeing the difference between interpreted and compiled code.
> SBCL always compiles code while CLISP does it only on demand.
:
> See 3.2.2.3 in the standard where it says that
>
>   "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."

Alright, thanks for the quick answer. So, is it recommended to compile
everything in sight while I am still trying to get a hang of CL?

Regards,
Mattias.
From: Harald Hanche-Olsen
Subject: Re: Closures in CLISP. (Newbie question)
Date: 
Message-ID: <pcomzjzc508.fsf@shuttle.math.ntnu.no>
+ "Mattias Nilsson" <········@bredband.net>:

| Alright, thanks for the quick answer. So, is it recommended to compile
| everything in sight while I am still trying to get a hang of CL?

It is recommended to keep special and non-special variables very, very
separate.  Give the former names with *asterisks* around them, and
don't do that to the latter.  Then you should be okay.

(Interpreted code is often easier to debug, as in poking around in the
debugger.)

-- 
* Harald Hanche-Olsen     <URL:http://www.math.ntnu.no/~hanche/>
- Debating gives most of us much more psychological satisfaction
  than thinking does: but it deprives us of whatever chance there is
  of getting closer to the truth.  -- C.P. Snow
From: Mattias Nilsson
Subject: Re: Closures in CLISP. (Newbie question)
Date: 
Message-ID: <1132527908.520237.277290@g47g2000cwa.googlegroups.com>
Harald Hanche-Olsen wrote:

> It is recommended to keep special and non-special variables very, very
> separate.  Give the former names with *asterisks* around them, and
> don't do that to the latter.  Then you should be okay.

Yes, I know about that. What I put in my OP was just my playing around,
trying to get a more solid grip on things... And this has certainly
made me aware of a difference between compiled and interpreted
CL, but I do not think that that is a topic for me to get into just
yet...

Regards,
Mattias.
From: Thomas F. Burdick
Subject: Re: Closures in CLISP. (Newbie question)
Date: 
Message-ID: <xcvlkzisbkz.fsf@conquest.OCF.Berkeley.EDU>
"Mattias Nilsson" <········@bredband.net> writes:

> Harald Hanche-Olsen wrote:
> 
> > It is recommended to keep special and non-special variables very, very
> > separate.  Give the former names with *asterisks* around them, and
> > don't do that to the latter.  Then you should be okay.
> 
> Yes, I know about that. What I put in my OP was just my playing around,
> trying to get a more solid grip on things... And this has certainly
> made me aware of a difference between compiled and interpreted
> CL, but I do not think that that is a topic for me to get into just
> yet...

If you have a tendancy to learn things by poking at them, it will be
hard to avoid tackling that difference bit-by-bit as you go along.
When you compile something, its semantics become (a lot more) static
based on the definitions available when you compile it.  When
something is interpreted, its meaning is computed anew every time you
use it.  Sometimes one is more in line with newbie-intuition,
sometimes the other.  Choosing one all the time won't necessarily make
your life easier right now -- and in the long run, having a good grasp
on the different times that exist in Lisp is valuable.

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | Free Mumia Abu-Jamal! |
     ,--'    _,'   | Abolish the racist    |
    /       /      | death penalty!        |
   (   -.  |       `-----------------------'
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: Pascal Bourguignon
Subject: Re: Closures in CLISP. (Newbie question)
Date: 
Message-ID: <87mzjyyi1u.fsf@thalassa.informatimago.com>
"Mattias Nilsson" <········@bredband.net> writes:

> Harald Hanche-Olsen wrote:
>
>> It is recommended to keep special and non-special variables very, very
>> separate.  Give the former names with *asterisks* around them, and
>> don't do that to the latter.  Then you should be okay.
>
> Yes, I know about that. What I put in my OP was just my playing around,
> trying to get a more solid grip on things... And this has certainly
> made me aware of a difference between compiled and interpreted
> CL, but I do not think that that is a topic for me to get into just
> yet...

While CL tried to reduce the semantic differences between interpreted
code and compiled code, implementations are still allowed to leave
quite a number of significant differences.  To reduce these remaining
differences (to avoid them!) conforming programs must follow some
constrains:

http://www.lispworks.com/documentation/HyperSpec/Body/03_bbc.htm


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

In a World without Walls and Fences, 
who needs Windows and Gates?
From: Harald Hanche-Olsen
Subject: Re: Closures in CLISP. (Newbie question)
Date: 
Message-ID: <pcoveync62d.fsf@shuttle.math.ntnu.no>
+ "Mattias Nilsson" <········@bredband.net>:

| (let ((counter 0))
|   (defun new-id () (incf counter))
|   (defun reset-id () (setq counter 0)))
|
| The way I think I understand closures, there should be no way
| of tampering with the value of counter as used by the two closures
| in the lines above, except by evaluating the forms (new-id) and
| (reset-id).
|
| However, when I later do (defparameter counter 17) in
| CLISP (v. 2.34), (new-id) next evaluates to 18. Then, if I do
| (makunbound 'counter), the closures refuse to work.

Sounds fishy, /unless/ counter was already prolaimed special when you
created the closure.  (Which would be bad form anyway.  Use *starred*
variable names for such purposes.)

I believe even an interpreter has to do enough work at function
definition time to settle the special-or-not question once and for
all (a compiler certainly must).

-- 
* Harald Hanche-Olsen     <URL:http://www.math.ntnu.no/~hanche/>
- Debating gives most of us much more psychological satisfaction
  than thinking does: but it deprives us of whatever chance there is
  of getting closer to the truth.  -- C.P. Snow
From: Harald Hanche-Olsen
Subject: Re: Closures in CLISP. (Newbie question)
Date: 
Message-ID: <pcoirunc4xj.fsf@shuttle.math.ntnu.no>
+ Harald Hanche-Olsen <······@math.ntnu.no>:

| I believe even an interpreter has to do enough work at function
| definition time to settle the special-or-not question once and for
| all (a compiler certainly must).

But Edi Weitz' response seems to contradict me on this point.
I'm ready to be further enlightened, if someone will point out chapter
and verse.

-- 
* Harald Hanche-Olsen     <URL:http://www.math.ntnu.no/~hanche/>
- Debating gives most of us much more psychological satisfaction
  than thinking does: but it deprives us of whatever chance there is
  of getting closer to the truth.  -- C.P. Snow
From: Thomas F. Burdick
Subject: Re: Closures in CLISP. (Newbie question)
Date: 
Message-ID: <xcvhda6sb8q.fsf@conquest.OCF.Berkeley.EDU>
Harald Hanche-Olsen <······@math.ntnu.no> writes:

> + Harald Hanche-Olsen <······@math.ntnu.no>:
> 
> | I believe even an interpreter has to do enough work at function
> | definition time to settle the special-or-not question once and for
> | all (a compiler certainly must).
> 
> But Edi Weitz' response seems to contradict me on this point.
> I'm ready to be further enlightened, if someone will point out chapter
> and verse.

There is no chapter and verse to cite.  The burden is the other way:
why *would* the interpreter have to do that work?  All that an
interpreter needs to do is evaluate forms on demand.  A simple CL
interpreter might involve code like the following:

  ;; For PROGN, the interpreter has some real work to do
  (define-interpreter progn env (&rest body)
    (let (results)
      (dolist (form body)
        (setf results (multiple-value-list (eval-in-env form env))))
      (values-list results)))

  (defstruct ifunction env params body)

  ;; Not so for LAMBDA
  (define-interpreter lambda env (params &rest body)
    (make-ifunction :env env :params params :body body))

Notice the lack of code walking on LAMBDA, which is at the heart of
the difference between compiled and interpreted code.

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | Free Mumia Abu-Jamal! |
     ,--'    _,'   | Abolish the racist    |
    /       /      | death penalty!        |
   (   -.  |       `-----------------------'
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: Harald Hanche-Olsen
Subject: Re: Closures in CLISP. (Newbie question)
Date: 
Message-ID: <pcofyppocn6.fsf@shuttle.math.ntnu.no>
+ ···@conquest.OCF.Berkeley.EDU (Thomas F. Burdick):

| Harald Hanche-Olsen <······@math.ntnu.no> writes:
|
|> I'm ready to be further enlightened, if someone will point out chapter
|> and verse.
|
| There is no chapter and verse to cite.

I was afraid of that.  8-)


| The burden is the other way: why *would* the interpreter have to do
| that work?

I guess I had been under the mistaken impression that the interpreter
would do some form of minimal compilation, in the CLHS 3.2.2.2 sense.
But of course, it doesn't seem to say so anywhere.

| All that an
| interpreter needs to do is evaluate forms on demand.  A simple CL
| interpreter might involve code like the following:
|
| [...]
|
|   (defstruct ifunction env params body)
|
|   ;; Not so for LAMBDA
|   (define-interpreter lambda env (params &rest body)
|     (make-ifunction :env env :params params :body body))
|
| Notice the lack of code walking on LAMBDA, which is at the heart of
| the difference between compiled and interpreted code.

Ah, but one could argue that the environment argument might contain
information to the effect that the lexical variable in the closure is
in fact lexical and not special.  But again, I now understand that the
standard does not seem to mandate this; but I think it is not
unreasonable.

-- 
* Harald Hanche-Olsen     <URL:http://www.math.ntnu.no/~hanche/>
- Debating gives most of us much more psychological satisfaction
  than thinking does: but it deprives us of whatever chance there is
  of getting closer to the truth.  -- C.P. Snow