Lisp 从s表达式创建lambda

Lisp 从s表达式创建lambda,lisp,lambda,eval,common-lisp,closures,Lisp,Lambda,Eval,Common Lisp,Closures,我有一个s表达式绑定到Common Lisp中的一个变量: (defvar x '(+ a 2)) 现在,我想创建一个函数,在调用该函数时,在定义表达式的范围内对其求值。我试过这个: (let ((a 4)) (lambda () (eval x))) 及 但这两个都会产生一个问题:EVAL将在顶层对代码求值,因此我无法捕获表达式中包含的变量。请注意,我不能将LET表单放入EVAL中。有什么解决办法吗 编辑:那么,如果没有解决评估问题的方法,还有什么方法可以做到呢 编辑:有一个关于我到底

我有一个s表达式绑定到Common Lisp中的一个变量:

(defvar x '(+ a 2))
现在,我想创建一个函数,在调用该函数时,在定义表达式的范围内对其求值。我试过这个:

(let ((a 4))
  (lambda () (eval x)))

但这两个都会产生一个问题:EVAL将在顶层对代码求值,因此我无法捕获表达式中包含的变量。请注意,我不能将LET表单放入EVAL中。有什么解决办法吗

编辑:那么,如果没有解决评估问题的方法,还有什么方法可以做到呢


编辑:有一个关于我到底想做什么的问题。我正在写一个编译器。我想接受在定义表达式的词法环境中变量闭合的s表达式。将其编写为宏可能确实更好。

CLISP实现了一个扩展,用于在词汇环境中计算表单。从它是一个扩展的事实来看,我怀疑您不能以标准兼容的方式来实现这一点

(ext:eval-env x (ext:the-environment))

请参阅。

在Common Lisp中,您可以定义允许您将环境传递给
(eval…
)的选项<代码>*evalhook*与平台无关。

您想要解决的实际问题是什么?最有可能的是,你试图以错误的方式解决它。词法绑定用于在其范围内以词法形式出现的内容,而不是用于从外部获得的随机内容

也许你想要一个动态的结束?虽然在一些Lisp方言中(据我所知,像Pico Lisp)存在这种情况,但在Common Lisp中并不存在这种情况

请注意,您可以执行以下类似操作:

(defvar *a*)
(defvar *x* '(+ *a* 2))  ;'

(let ((a 10))
  ;; ...
  (let ((*a* a))
    (eval *x*)))

不过,我建议您仔细考虑是否真的需要它。

您需要创建具有必要绑定的代码。在代码周围包装一个LET,并绑定您希望在代码中可用的每个变量:

(defvar *x* '(+ a 2))

(let ((a 4))
  (eval `(let ((a ,a))
           ,*x*)))

可以使用COMPILE将表达式编译为函数,然后使用PROGV在动态设置变量的环境中对所有编译后的函数进行funcy。或者,更好的方法是使用COMPILE将表达式编译成接受变量的函数

Compile将函数定义作为列表接受,并将其转换为函数。对于SBCL,此函数将编译为机器代码,并将高效执行

第一个选项(使用compile和progv):

第二种选择:

(defvar *fn* (compile nil '(lambda (a) (+ a 2))))
(funcall *fn* 4)
=>
6

你从哪里得到内部表达式?除非您是从外部源读取,否则可以尝试使用宏而不是eval。我是从外部源读取的。非常正确,它们似乎已被ANSI删除
(defvar *fn* (compile nil '(lambda () (+ a 2)))
(progv '(a) '(4) (funcall *fn*))
=>
6
(defvar *fn* (compile nil '(lambda (a) (+ a 2))))
(funcall *fn* 4)
=>
6