[comp.lang.lisp] Scope of EVAL

eliot@phoenix.Princeton.EDU (Eliot Handelman) (10/28/88)

In article <249@pitstop.UUCP> robv@pitstop.UUCP (Rob Vollum) writes:

>Of course, there are the other problems, such as EVAL not being
>able to "see" lexical variables, etc.

Is that really true?  In the following example, EVAL consults the lexical
environment, rather that the global.

(setq x nil)

And now (let* ((x t) (y x)) (eval y)) => t

The result of the first evalution sets y to x; yet EVAL gets the effective
lexical binding anyway. This also seems to work whether or not the code is
compiled and x is made special.  Can you give an example where that
isn't the case?

Eliot Handelman
Music, Princeton U.

andreasg@boulder.Colorado.EDU (Andreas Girgensohn) (10/28/88)

In article <4154@phoenix.Princeton.EDU> eliot@phoenix.Princeton.EDU (Eliot Handelman) writes:
>Is that really true?  In the following example, EVAL consults the lexical
>environment, rather that the global.
>
>(setq x nil)
>
>And now (let* ((x t) (y x)) (eval y)) => t

EVAL evaluates its argument so that the above call of eval is the same
as (eval 't).  (eval 'y) will lead to an error unless y is a special
variable.

Andreas Girgensohn
andreasg@boulder.colorado.edu

duff@eraserhead (David A Duff) (10/29/88)

In article <4154@phoenix.Princeton.EDU>, eliot@phoenix (Eliot Handelman) writes:
>In article <249@pitstop.UUCP> robv@pitstop.UUCP (Rob Vollum) writes:

[... stuff about eval only being able to perform evaluation in the top-level
environment.] 

>Is that really true?  In the following example, EVAL consults the lexical
>environment, rather that the global.

Yes.

>(setq x nil)
>And now (let* ((x t) (y x)) (eval y)) => t

Remember: eval is a function, and the semantics of lisp are such that when
evaluating a function application (a list whose car is neither a macro nor a
special form), the arguments are evaluated first, then the function is
applied.  So, basically, whatever you put in place of ... in "(eval ...)" ends
up getting evaluated TWICE -- once before eval is called and once after.  In
your example above, the eval function never sees the symbol y, but is instead
passed the value t.  

To better illustrate the difference between evaluation within a lexical
environment and evaluation in the top-level environment (the kind that the
lisp eval function does) you probably meant to try something like this:

(setq x nil)

;; here x is eval'd in lexical environment:
(let ((x t)) x) ==> t 

;; here x is eval'd in top-level environment:
(let ((x t)) (eval 'x)) ==> nil

Dave Duff                                     GE Research and Development Center
duff@eraserhead.steinmetz.ge.com                           Schenectady, New York
uunet!steinmetz!eraserhead!duff                                     518-387-5649
Dave Duff                                     GE Research and Development Center
duff@eraserhead.steinmetz.ge.com                           Schenectady, New York
uunet!steinmetz!eraserhead!duff                                     518-387-5649

robv@pitstop.UUCP (Rob Vollum) (11/02/88)

In article <4154@phoenix.Princeton.EDU> eliot@phoenix.Princeton.EDU (Eliot Handelman) writes:
>In article <249@pitstop.UUCP> robv@pitstop.UUCP (Rob Vollum) writes:
>
>>Of course, there are the other problems, such as EVAL not being
>>able to "see" lexical variables, etc.
>
>Is that really true?  In the following example, EVAL consults the lexical
>environment, rather that the global.
>
>(setq x nil)
>And now (let* ((x t) (y x)) (eval y)) => t
>
>The result of the first evalution sets y to x; yet EVAL gets the effective
>lexical binding anyway. This also seems to work whether or not the code is
>compiled and x is made special.  Can you give an example where that
>isn't the case?
>
>Eliot Handelman

In the example given above, you're not really EVALing a symbol; you're EVALing
the value of a symbol. Things worked out (in this case) because T is 
self-evaluating. If you had tried (let* ((x 'a) (y x)) (eval y)) you would
have gotten an error along the lines of "symbol A has no global value..."

To illustrate the point that EVAL cannot see the lexical environment, try this:

(setq x 'global-value)
(let ((x 'lexical-value)) (eval 'x))
--> GLOBAL-VALUE

(and remember, the initial SETQ *must* be a SETQ, and not a DEFVAR, since DEFVAR
proclaims things SPECIAL, after which they can never be lexical.)

As to why EVAL might be specified not to see lexical values of symbols: compilers
don't deal with symbol names when accessing lexical variables, generally. They
deal only in stack offsets. In fact, in your example above, what's happening is
somewhere along the following lines: the compiler creates two slots on the stack;
one for x, one for y. When compiling the code for the "eval" expression, it 
generates something like "load the contents of stack-pointer+2". It never
mentions Y at all. So, when EVALing symbols at run-time, the system really has
no choice but to grab the top-level value.

Rob Vollum
UUCP: ...sun!sunne!robv
ARPA: rvollum@sun.com