From: Yu-shen Ng
Subject: LISP PROBLEM
Date: 
Message-ID: <5071@zodiac.UUCP>
(eval form) normally evaluates "form" in a null lexical scope.

How can I do an "eval" within the lexical scope from which the "eval" is called?
     e.g. I would like to do the following:

       (defun test ()
	 (let ((form)
	       (a ..)
	       (b ..)
	       (c ..)
	       (any-number-of-variables 
		    ....
		       ))
           ... 
	   ...
	   (eval form)))       ; where "form" may reference any of the variables
                               ;  in the lexical scope when eval is called.
	 
Suppose that you do not even know the names of all the local variables
	that "form" may reference.

It seems to me that you have to use *evalhook* and evalhook, but I can't seem to get them to
  work for me for any general "form".


Please send any helpful ideas to

······@ads.com

From: Barry Margolin
Subject: Re: LISP PROBLEM
Date: 
Message-ID: <24909@think.UUCP>
In article <····@zodiac.UUCP> ······@ads.com (Yu-shen Ng) writes:
>How can I do an "eval" within the lexical scope from which the "eval" is called?

You can't.  EVAL is an ordinary function, so it has no idea what
lexical context it was called in (only special forms and macros can
access the lexical context).

How would it possibly work in a compiled function, when references to
lexical variables have been converted to stack frame offsets, and the
names of the local variables have been discarded?  If the Lisp
implementation saves the local variable information (as it does on
Lisp Machines) then there will likely be an implementation-specific
function for evaluating in a given lexical environment (for use by the
debugger, for instance); a common mechanism is to allow EVAL to take
an optional second argument, which is the lexical environment.
However, Common Lisp doesn't require this capability.

Why do you need this capability?  If the form you want to evaluate is
coming from outside the function, how could it possibly know the names
of your local variables?

Perhaps you should describe what you are trying to accomplish, since I
suspect you may be going about it wrong.  It is almost always wrong to
call EVAL explicitly from a function.  You can usually do what you
want with FUNCALL or APPLY.

Barry Margolin
Thinking Machines Corp.

······@think.com
{uunet,harvard}!think!barmar
From: Aaron Endelman
Subject: EVAL with environment (was: Re: LISP PROBLEM)
Date: 
Message-ID: <63216@sun.uucp>
In article <·····@think.UUCP> ······@kulla.think.com.UUCP (Barry Margolin) writes:
>In article <····@zodiac.UUCP> ······@ads.com (Yu-shen Ng) writes:
>>How can I do an "eval" within the lexical scope from which the "eval" is called?
>
>You can't.  EVAL is an ordinary function, so it has no idea what
>lexical context it was called in (only special forms and macros can
>access the lexical context).
>
>How would it possibly work in a compiled function, when references to
>lexical variables have been converted to stack frame offsets, and the
>names of the local variables have been discarded?  If the Lisp
>implementation saves the local variable information (as it does on
>Lisp Machines) then there will likely be an implementation-specific
>function for evaluating in a given lexical environment (for use by the
>debugger, for instance); a common mechanism is to allow EVAL to take
>an optional second argument, which is the lexical environment.
>However, Common Lisp doesn't require this capability.
>
>Why do you need this capability?  If the form you want to evaluate is
>coming from outside the function, how could it possibly know the names
>of your local variables?
>
>Perhaps you should describe what you are trying to accomplish, since I
>suspect you may be going about it wrong.  It is almost always wrong to
>call EVAL explicitly from a function.  You can usually do what you
>want with FUNCALL or APPLY.

I'd like to put in a plug for this capability, too.  I'd like to see eval
take an optional environment arg as part of the CL standard.  Sometimes
there's a real need to be able to generate interpreted code on the fly which
retains lexical context.  As things stand, let's say I programmatically
generate a function foo which then invokes a previously-compiled macro bar:

(defun foo (x)     ; interpreted
   (bar x))

(defmacro bar (y)  ; compiled
  `(progn 
     (...some big hairy form, possibly invoking more macros...)
     ,y))

So (foo 'a) => a

Postulate also that I don't want to compile foo because the implicit
macroexpansion of bar at that time would send me to the coffee machine.

The problem is avoiding all the overhead involved in macroexpanding bar's
body at run time.  What I'd like is:

(defun foo (x)     ; interpreted
  (eval '(bar x) *current-environment*))

(defun bar (y)     ; compiled
  (...some big hairy form...)
  y)

------------------------------------------------------------------------
Gillian:  Sure you won't change your mind?
Spock: Is there something wrong with the one I have?

Aaron Endelman                                  ········@sun.com
Symbolic Programming Group                      ...!sun!endelman
Software Products Division
Sun Microsystems, Inc.
------------------------------------------------------------------------
From: Flash Sheridan
Subject: macroexpansion Environments in CL (was: Re: EVAL with environment)
Date: 
Message-ID: <573@sequent.cs.qmc.ac.uk>
I admit it is a good thing not to specify the format of environments, but I
wish CL defined a bit more access to them.  The only way I could figure out
to find _any_ environment of any sort in pure Common Lisp is:

(defun print-env  ()
  (macrolet ((fudge (&environment env)
		    `',env))
    (print "the environment is:") (terpri)
    (print (fudge) )
    ))

It took me entirely too long to figure this out, largely because of appalling
proof-reading in CLtL.

From: ·····@ee.qmc.ac.uk (Flash Sheridan)
Reply-To: ········@nss.cs.ucl.ac.uk
or_perhaps_Reply_to: ·····@cs.qmc.ac.uk
From: Jeff Dalton
Subject: Re: LISP PROBLEM
Date: 
Message-ID: <522@aiva.ed.ac.uk>
In article <····@zodiac.UUCP> ······@ads.com (Yu-shen Ng) writes:
>(eval form) normally evaluates "form" in a null lexical scope.  How can
>I do an "eval" within the lexical scope from which the "eval" is called?

>It seems to me that you have to use *evalhook* and evalhook, but I can't
>seem to get them to work for me for any general "form".

You can indeed use *EVALHOOK* and EVALHOOK in interpreted code (see
below), but the trick will not work for compiled code.  Common Lisp
does not encourage this style of programming because it makes life
difficult for the compiler and because code written that way is often
hard to analyze.  Nonetheless, it would be possible to implement a
Lisp in which EVAL did work with lexical environments.

Since EVAL is a function, it must be given the environment as a
parameter. That implies that the environment is an explicit object,
and while interpreters may use such objects, compiled code often does
not.  However, suppose there were a special form that returned a
lexical environment.  The compiler could notice the presence of that
operation and use an explicit structure only then.  [Or, if EVAL were
a special form, it could do this for EVAL.]  Compilers already make a
similar analysis for closures, which also must include an environment.
[However, the closure env is not necessarily one in which values can
be looked up by name -- since the variables involved can all be known
at compile time, the code could just use an offset.]

The idea here is that something, (GET-ENV) perhaps, would return the
current lexical environment "around" the GET-ENV call.  This can be
done for interpreted CL as follows:

;;; Return the current lexical environment.

(defmacro get-env ()
  '(let ((*evalhook*
          #'(lambda (form &optional env) env)))
     (eval 'nil)))

;;; Eval w.r.t. an environment

(defun enveval (form lexenv)
  (evalhook form nil nil lexenv))

Now, 

   > (let ((a 10)) (get-env))
   #<an environment>
   > (enveval 'a *)
   10

Another appraoch is to provide an environment for certain names only.
This is something you can write yourself -- Lisp doesn't have to provide
it.

>Suppose that you do not even know the names of all the local variables
>	that "form" may reference.

It may be inconvenient, but you often can know the names simply by
looking at the code around the EVAL.  This will not work if the EVAL
is part of a macro expansion.  An alternative to listing the names to
put in the environment is to define varsions of LET, FLET, etc. that
make their bindings visible to GET-ENV.  At this point, you might be
better off using dynamic scoping instead, but perhaps you want
closures over these variables too.  Anyway, below is some code that
does this for LET.

     ------------------------------------------------------------

;;; Visible let [vlet] -- makes bindings visible to get-env.

(defmacro vlet (binds &body body)
  ;; syntax is (VLET ((var init)...) form...)
  `(vlet-1 () ,binds ,@body))

;;; vlet-1 redefines vlet to keep track of nesting.
;;; It also defines get-env to return an env that allows
;;; ref to everything bound by vlet.

(defmacro vlet-1 (nest binds &body body)
  (let ((nest (append nest (mapcar #'car binds))))
    `(let ,binds
       (macrolet
	   ((vlet (binds &body body)
	      `(vlet-1 ,',nest
		       ,binds
		       ,@body))
	    (get-env ()
	      `(enclose ,',nest)))
	 ,@body))))

;;; A lexical environment is represented by a structure containing
;;; functions that access or set the variables.

(defstruct (lexenv (:print-function print-lexenv))
  names getter setter)

(defun print-lexenv (lexenv stream depth)
  (format stream "#<Lexenv ~S>"
	  (mapcar #'(lambda (name)
		      (list name (symeval-in-env lexenv name)))
		  (lexenv-names lexenv))))

;;; Enclose makes an env struct for the variables indicated.
;;; It must be called in a context where the variables are
;;; lexically visible.

(defmacro enclose (vars)
  `(make-lexenv
     :names ',vars
     :getter
       #'(lambda (name)
	   (ecase name
	     ,@(mapcar #'(lambda (v) `(,v ,v))
		       vars)))
     :setter
       #'(lambda (name val)
	   (ecase name
	     ,@(mapcar #'(lambda (v) `(,v (setq ,v val)))
		       vars)))))

;;; Functions for getting and setting variables in environments.

(defun symeval-in-env (env name)
  (funcall (lexenv-getter env) name))

(defun set-in-env (env name val)
  (funcall (lexenv-setter env) name val))

(defsetf symeval-in-env set-in-env)

;;; Eval relative to an environment.  Symbol-macro-let is used
;;; to turn variable references into function calls that look
;;; in the environment.  Symbol-macro-let is to let what macrolet
;;; is to flet (or is it labels?); it is part of CLOS.

(defun enveval (form env)
  ;; needs symbol-macro-let
  (eval
   `(let ((the-env ',env))
      (symbol-macro-let
          ,(mapcar #'(lambda (name)
		       `(,name (symeval-in-env the-env ',name)))
		   (lexenv-names env))
	  ,form))))

     ------------------------------------------------------------

This code is provided primarily for entertainment value; I don't claim
it's a good way to do anything.  Nonetheless, through the magic of
macros, it does not create an environment unless GET-ENV is actually
called.

Jeff Dalton,                      JANET: ········@uk.ac.ed             
AI Applications Institute,        ARPA:  ·················@nss.cs.ucl.ac.uk
Edinburgh University.             UUCP:  ...!ukc!ed.ac.uk!J.Dalton