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)
<············@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."
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
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 ***
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.
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.