From: Philippe Lorin
Subject: Trying to understand warning:  Declaring X special
Date: 
Message-ID: <434a4c14$0$21211$626a54ce@news.free.fr>
I don't understand why I get a warning with this (in a fresh REPL):

(let ((x 1))
   (declare (special x))
   (eval '(setf x 2))
   (print x) (terpri))

Warning:  Declaring X special.
(using CMUCL)



I don't get one with this:

(let ((x 1))
   (declare (special x))
   (print x) (terpri))



Well, I *am* declaring X as special, so I'd expect it to be so 
declared--why warn me? What unexpected behaviour am I exposing myself to?
I understand that in the second case, X being special is of no 
consequence, but still I declared it so... Getting a warning there would 
surprise me less.

(Note: I did look for help on warnings in the CMUCL manual, but found 
nothing; any pointers welcome)

From: Juho Snellman
Subject: Re: Trying to understand warning:  Declaring X special
Date: 
Message-ID: <slrndkkmbk.50o.jsnell@sbz-30.cs.Helsinki.FI>
<············@gmail.com> wrote:
> I don't understand why I get a warning with this (in a fresh REPL):
> 
> (let ((x 1))
>    (declare (special x))
>    (eval '(setf x 2))
>    (print x) (terpri))
> 
> Warning:  Declaring X special.
> (using CMUCL)
[...]
> Well, I *am* declaring X as special, so I'd expect it to be so
> declared--why warn me?

The scope of the declaration is lexical (clhs 3.3.4):

  The scope of a bound declaration is the same as the lexical scope of
  the binding to which it applies; for special variables, this means
  the scope that the binding would have had had it been a lexical
  binding. 

EVAL evaluates the code in the null lexical environment, so the 
declaration isn't in scope when (SETF X 2) is evaluated.

-- 
Juho Snellman
"Premature profiling is the root of all evil."
From: Philippe Lorin
Subject: Re: Trying to understand warning:  Declaring X special
Date: 
Message-ID: <434a6484$0$28003$626a14ce@news.free.fr>
Juho Snellman wrote:
> The scope of the declaration is lexical

Thank you, this is what I missed. So, if I want the X in the EVAL to 
have the same binding as the X in the LET, is this the correct thing to 
write? :

(let ((x 1))
   (declare (special x))
   (eval '(progn
           (defvar x)
           (setf x 2)))
   (print x) (terpri))
From: Christophe Rhodes
Subject: Re: Trying to understand warning:  Declaring X special
Date: 
Message-ID: <sqbr1xbk0l.fsf@cam.ac.uk>
Philippe Lorin <············@gmail.com> writes:

> Thank you, this is what I missed. So, if I want the X in the EVAL to 
> have the same binding as the X in the LET, is this the correct thing to 
> write? :
>
> (let ((x 1))
>   (declare (special x))
>   (eval '(progn
>           (defvar x)
>           (setf x 2)))
>   (print x) (terpri))

That is conforming code and does what you say, but it also establishes
a pervasive special declaration for X.  You probably want instead

(let ((x 1))
  (declare (special x))
  (eval '(locally (declare (special x)) 
           (setf x 2)))
  (print x) (terpri))

so that the special declaration only applies to the evaluated
expression, not the entire session.

Christophe
From: Barry Margolin
Subject: Re: Trying to understand warning:  Declaring X special
Date: 
Message-ID: <barmar-BA73A4.09204910102005@comcast.dca.giganews.com>
In article <··············@cam.ac.uk>,
 Christophe Rhodes <·····@cam.ac.uk> wrote:

> Philippe Lorin <············@gmail.com> writes:
> 
> > Thank you, this is what I missed. So, if I want the X in the EVAL to 
> > have the same binding as the X in the LET, is this the correct thing to 
> > write? :
> >
> > (let ((x 1))
> >   (declare (special x))
> >   (eval '(progn
> >           (defvar x)
> >           (setf x 2)))
> >   (print x) (terpri))
> 
> That is conforming code and does what you say, but it also establishes
> a pervasive special declaration for X.  You probably want instead
> 
> (let ((x 1))
>   (declare (special x))
>   (eval '(locally (declare (special x)) 
>            (setf x 2)))
>   (print x) (terpri))
> 
> so that the special declaration only applies to the evaluated
> expression, not the entire session.

Or:

(let ((x 1))
  (declare (special x))
  (eval '(setf (symbol-value 'x) 2))
  (print x) (terpri))

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
From: Steven M. Haflich
Subject: Re: Trying to understand warning:  Declaring X special
Date: 
Message-ID: <xQF2f.378$q%.78@newssvr12.news.prodigy.com>
Philippe Lorin wrote:
> Juho Snellman wrote:
> Thank you, this is what I missed. So, if I want the X in the EVAL to 
> have the same binding as the X in the LET, is this the correct thing to 
> write? :
> 
> (let ((x 1))
>   (declare (special x))
>   (eval '(progn
>           (defvar x)
>           (setf x 2)))
>   (print x) (terpri))

I think you are still missing something:  Essentially any use of
the eval function is the result of confusion.  It is almost never
the right thing, and almost never necessary.

Does that give you a hint how a Lisp programmer would write the
above code?  There is nothing remarkable about the code, so all
you need is the code.  You don't need meta functions eval.
From: Philippe Lorin
Subject: Re: Trying to understand warning:  Declaring X special
Date: 
Message-ID: <434ce358$0$21218$626a54ce@news.free.fr>
Steven M. Haflich wrote:
> I think you are still missing something:  Essentially any use of
> the eval function is the result of confusion.  It is almost never
> the right thing, and almost never necessary.
> 
> Does that give you a hint how a Lisp programmer would write the
> above code?  There is nothing remarkable about the code, so all
> you need is the code.  You don't need meta functions eval.

I am not sure I understand this last paragraph. Of course, in my 
example, eval is superfluous. I tried to strip my problem to the 
barebones so that people could help without having to dive into a big 
program.

In the code I am writing, and which led me to ask that question, I think 
that eval, or something similar, is needed. As I'm still a newbie, I 
can't be sure; I plan to publish the whole code when it's done and I 
hope you and everybody interested will point at any abusive uses of eval 
(among other mistakes!).

I'm making something in which the user can type Lisp code and have it 
executed, after a few transforms which give it a context. I'm using a 
lot of eval, progv and read-from-string.

There is one (unrelated) case where I find myself using eval while 
really feeling it's not right; it's when I'm writing something like:
(eval `(some-macro ,x))
where some-macro doesn't evaluate its argument. I do that a lot. If this 
is a common mistake I'll welcome a common cure.