From: Mertens Marc
Subject: Lexical environment's in lisp
Date: 
Message-ID: <31E7749D.48E16F7C@ibm.net>
Hello, 
         can someone help me with the following problem. I want to
execute a piece of code in the lexical environment of
 another function. More in detail I want to do something like :

          (defun test ()
	      (let ((v 10))
		 (flet ((power (lambda (n) (* n n))))
		   (eval code))))


           (setf code '(setf a (power n)))

           (test)

           code ===> 100 , so when code is evaluated it should use the
values 10 for n and (lambda (n) (* n n)) 
                                       for power. I know 'eval' is not
able to do this , but is there a way of establishing this ??


Thanks a lot in advance

Marc Mertens

·······@ibm.net

From: Ralf Muschall
Subject: Re: Lexical environment's in lisp
Date: 
Message-ID: <6CpOg0qWy0B@elefant.Jena.Thur.De>
·······@ibm.net (Mertens Marc)  wrote in comp.lang.lisp <·················@ibm.net>:

> Hello,
>          can someone help me with the following problem. I want to
> execute a piece of code in the lexical environment of
>  another function. More in detail I want to do something like :
>

(evalhook <form> <evalhookfctn> <applhookfctn> &optional <env>)

might be what you need. It is described in CLtL2, chapter 20 (CLtL2 is
also available in LaTeX or HTML (see the FAQ for URLs)).

The following code is stolen from Xlisp, but works also with CLISP
(I renamed some functions in order to avoid name clashes).
The original file can be found as evalenv.lsp in the Xlisp 2.1g
distribution.


(defmacro get-current-environment ()
   '(let ((*evalhook* (lambda (x env) env)))
       (eval nil)))

(defmacro eval-in-current-env (arg); evaluate in current environment
   `(evalhook ,arg nil nil (get-current-environment)))

;;; the following function is mine and might therefore be buggy:
(defun eval-in-given-env (arg env)
   (evalhook arg nil nil env))

HTH, Ralf
From: Christian Rathke
Subject: Re: Lexical environment's in lisp
Date: 
Message-ID: <rathke-1507960931500001@news>
In article <·················@ibm.net>, Mertens Marc <·······@ibm.net> wrote:

>Hello, 
>         can someone help me with the following problem. I want to
>execute a piece of code in the lexical environment of
> another function. More in detail I want to do something like :
>
>          (defun test ()
>	      (let ((v 10))
>		 (flet ((power (lambda (n) (* n n))))
>		   (eval code))))
>
>
>           (setf code '(setf a (power n)))
>
>           (test)
>
>           code ===> 100 , so when code is evaluated it should use the
> ...

(defmacro test-code-generator (code)
  `(defun test ()
       (let ((n 10))
          (flet ((power (n) (* n n)))
             ,code))))

(test-code-generator (setf a (power n)))

(test) ==> 100

-- 
Christian Rathke                        ······@informatik.uni-stuttgart.de
Institut fuer Informatik, Universitaet Stuttgart   Tel: (+49 711) 7816-436
Breitwiesenstr. 20-22, D-70565 Stuttgart, Germany  Fax: (+49 711) 7816-340
http://www.informatik.uni-stuttgart.de/ifi/is/christian.html
From: David Duff
Subject: Re: Lexical environment's in lisp
Date: 
Message-ID: <duff-1507960141440001@news>
In article <·················@ibm.net>, Mertens Marc <·······@ibm.net> wrote:

> Hello, 
>          can someone help me with the following problem. I want to
> execute a piece of code in the lexical environment of
>  another function. More in detail I want to do something like :
> 
>           (defun test ()
>               (let ((v 10))
>                  (flet ((power (lambda (n) (* n n))))
>                    (eval code))))
> 
> 
>            (setf code '(setf a (power n)))
> 
>            (test)
> 
>            code ===> 100 , so when code is evaluated it should use the
> values 10 for n and (lambda (n) (* n n)) 
>                                        for power. I know 'eval' is not
> able to do this , but is there a way of establishing this ??
> 

flet has no effect on the evaluation of the form bound to code in the
example above.  the bindings of flet are lexical in nature, meaning that
they only affect references to the bound symbols which appear within the
binding form.

i assume where you used "v" in your example above, you meant to use "n"...

what you probably want is a macro like:

(defmacro test (&body code)
  `(flet ((power (lambda (n) (* n n))))
     (let ((n 10))
        ,@code)))

(test (setf a (power n))) => 100

-- 
David Duff
MITRE Corporation AI Technical Center
McLean, Virginia  USA
From: Kent Pitman
Subject: Re: Lexical environment's in lisp
Date: 
Message-ID: <KMP.96Jul15225337@romulus.harlqn.co.uk>
In article <·················@ibm.net> Mertens Marc <·······@ibm.net> writes:

> I want to execute a piece of code in the lexical environment of
> another function.

Well, the whole point of lexical environments is to place a bound on the
number of clients of the given environment so that the compiler can do
really good optimization, sometimes eliminating the names of local
variables or bound functions by inlining them such that the name is no
longer needed.  If someone is going to come along later and access the
environment, the compiler will not be able to do this.

Also, lexical environments allow you to prove program correctness
because you can look at the code and be sure that no one will come
along who wants to mess with them.

You can mess around with the global environment by introspecting into
global data structures, which are not subject to these constraints.
For example, you can use PROGV to bind values to special variables
in a dynamic contour. e.g.,

 (DEFUN MY-EVAL (EXPRESSION VAR-ENV)
   (PROGV (MAPCAR #'FIRST VAR-ENV) (MAPCAR #'SECOND VAR-ENV)
     (EVAL EXPRESSION)))

 (MY-EVAL '(+ A B) '((A 1) (B 2))) => 3

Or you could attach them lexically by doing:

 (DEFUN MY-EVAL-1 (EXPRESSION BINDINGS)
   (EVAL `(LET ,BINDINGS ,EXPRESSION)))

 (MY-EVAL-1 '(+ A B) '((A 1) (B 2)))

This second technique will adapt itself to function bindings, as in:

 (DEFSTRUCT MY-ENV
   (BINDINGS  '())
   (FBINDINGS '()))

 (DEFUN MY-EVAL-2 (EXPRESSION ENV)
   (EVAL `(LET ,(MY-ENV-BINDINGS ENV) 
            (LABELS ,(MY-ENV-FBINDINGS ENV)
              ,EXPRESSION))))

 (DEFVAR *MY-SAMPLE-ENV* 
   (MAKE-MY-ENV :BINDINGS '((A 5))
                :FBINDINGS '((F (X) (IF (ZEROP X) 1 (* X (F (- X 1))))))))

 (MY-EVAL-2 '(F A) *MY-SAMPLE-ENV*) => 120

Of course, if you SETQ the variables during the execution, the assignment
won't change MY-ENV.  But with a little work you could change the LET it 
constructs to put the final values of each variable back into the binding 
at the very end of the LET.  (I'll leave that as an "exercise to the reader".)

Whether or not these are powerful enough to suit your needs will, I suppose,
depend on the nature of your needs.  But hopefully it's enough to get you
thinking.

You may also want to check into the use of UNWIND-PROTECT.

--Kent Pitman
  ···@harlequin.com