clisp provides a facility to evaluate a form in a non null lexical environment. It works as follows
(let ((a 1) (b 2))
(ext:eval-env '(format t "a is ~A b is ~A~%" a b) (ext:the-environment))) a is 1 b is 2 NIL
The clisp documentation gives Macro EXT:THE-ENVIRONMENT. As in Scheme, the macro (EXT:THE-ENVIRONMENT) returns the current lexical environment. This works only in interpreted code and is not compilable!
Function (EXT:EVAL-ENV form &OPTIONAL environment). evaluates a form in a given lexical environment, just as if the form had been a part of the program that the environment came from.
I was wondering if ECL has something analogous or could be added easily. Looking in the ECL source I saw a si::eval-with-env function in file ecl-16.1.3/src/c/compiler.d .If you do
(find-symbol "EVAL-WITH-ENV" "SYSTEM")
SI:EVAL-WITH-ENV :EXTERNAL
which suggests that the function is not just for internal use. But scanning the documentation , I didn't see it mentioned. I tried
(defmacro env-eval (form &environment env) `(ext:eval-with-env ,form (quote ,env))) ENV-EVAL
(let ((v 12)) (env-eval '(print v)))
The variable V is unbound. Broken at EVAL.No restarts available. Broken at EVAL.
So is there a way to achieve this ?
Hello Spiros,
I was wondering if ECL has something analogous or could be added easily.
no such interfaces are present currently in ECL. Even with bytecompiler code is not interpreted but always minimally compiled.
Looking in the ECL source I saw a si::eval-with-env function in file ecl-16.1.3/src/c/compiler.d .If you do
(find-symbol "EVAL-WITH-ENV" "SYSTEM")
SI:EVAL-WITH-ENV :EXTERNAL
which suggests that the function is not just for internal use. But
scanning
the documentation , I didn't see it mentioned.
symbols in package system are part of ecl internals (this is documented), they are not part of the api. Only symbols reexported to ext are somewhat stable.
I tried
(defmacro env-eval (form &environment env) `(ext:eval-with-env ,form (quote ,env))) ENV-EVAL
(let ((v 12)) (env-eval '(print v)))
The variable V is unbound. Broken at EVAL.No restarts available. Broken at EVAL.
So is there a way to achieve this ?
eval-with-evn accepts the lexical environment while environment put there by defmacro is something else. You may use a hack, but I do not guarantee it will work in all scenarios:
CL-USER> (defmacro eval-with-lexenv-ala-clisp (form) `(let ((lexenv (nth-value 1 (function-lambda-expression (lambda ()))))) (si:eval-with-env ,form lexenv))) EVAL-WITH-LEXENV-ALA-CLISP CL-USER> (let ((v 42)) (eval-with-lexenv-ala-clisp '(print v)))
42 42
Most notably this *won't* work in normally compiled code.
Best regards, Daniel
On Thu, 11 Jul 2019 21:39:34 +0200 Daniel Kochmański wrote:
Looking in the ECL source I saw a si::eval-with-env function in file ecl-16.1.3/src/c/compiler.d .If you do
(find-symbol "EVAL-WITH-ENV" "SYSTEM")
SI:EVAL-WITH-ENV :EXTERNAL
which suggests that the function is not just for internal use. But scanning the documentation , I didn't see it mentioned.
symbols in package system are part of ecl internals (this is documented), they are not part of the api. Only symbols reexported to ext are somewhat stable.
Ok , this confused me originally because I thought that "EXT" , "SYS" , "SYSTEM" were all nicknames for package "SI" .But it turns out that this was true in an older version and now "EXT" is a separate package.
I tried
(defmacro env-eval (form &environment env) `(ext:eval-with-env ,form (quote ,env))) ENV-EVAL
(let ((v 12)) (env-eval '(print v)))
The variable V is unbound. Broken at EVAL.No restarts available. Broken at EVAL.
So is there a way to achieve this ?
eval-with-evn accepts the lexical environment while environment put there by defmacro is something else. You may use a hack, but I do not guarantee it will work in all scenarios:
CL-USER> (defmacro eval-with-lexenv-ala-clisp (form) `(let ((lexenv (nth-value 1 (function-lambda-expression (lambda ()))))) (si:eval-with-env ,form lexenv))) EVAL-WITH-LEXENV-ALA-CLISP CL-USER> (let ((v 42)) (eval-with-lexenv-ala-clisp '(print v)))
42 42
Thanks , this looks promising.
Most notably this *won't* work in normally compiled code.
This won't be a problem.