从 s 表达式创建 lambda
我有一个 s 表达式绑定到 Common Lisp 中的变量:
(defvar x '(+ a 2))
现在我想创建一个函数,当调用该函数时,它会在定义它的范围内计算该表达式。 我已经尝试过:
(let ((a 4))
(lambda () (eval x)))
并且
(let ((a 4))
(eval `(lambda () ,x)))
但这两个都会产生一个问题:EVAL 将在顶层评估代码,因此我无法捕获表达式中包含的变量。 请注意,我不能将 LET 形式放入 EVAL 中。 有什么解决办法吗?
编辑:那么如果 EVAL 问题没有解决方案,还能怎么做呢?
编辑:有人问我到底想做什么。 我正在写一个编译器。 我想接受一个 s 表达式,其变量在定义该表达式的词法环境中关闭。 把它写成宏确实可能更好。
I have an s-expression bound to a variable in Common Lisp:
(defvar x '(+ a 2))
Now I want to create a function that when called, evaluates the expression in the scope in which it was defined. I've tried this:
(let ((a 4))
(lambda () (eval x)))
and
(let ((a 4))
(eval `(lambda () ,x)))
But both of these create a problem: EVAL will evaluate the code at the top level, so I can't capture variables contained in the expression. Note that I cannot put the LET form in the EVAL. Is there any solution?
EDIT: So if there is not solution to the EVAL problem, how else can it be done?
EDIT: There was a question about what exactly I am try to do. I am writing a compiler. I want to accept an s-expression with variables closed in the lexical environment where the expression is defined. It may indeed be better to write it as a macro.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您需要创建具有必要绑定的代码。 用 LET 包裹您的代码并绑定您想要在代码中可用的每个变量:
You need to create code that has the necessary bindings. Wrap a LET around your code and bind every variable you want to make available in your code:
CLISP 实现了一个扩展来评估词法环境中的形式。 由于它是一个扩展,我怀疑您无法以符合标准的方式做到这一点。
请参阅http://clisp.cons.org/impnotes.html#eval-environ。
CLISP implements an extension to evaluate a form in the lexical environment. From the fact that it is an extension, I suspect you can't do that in a standard-compliant way.
See http://clisp.cons.org/impnotes.html#eval-environ.
您想要解决的实际问题是什么? 最有可能的是,你试图以错误的方式解决这个问题。 词法绑定适用于词汇上出现在其范围内的事物,而不是您从外部获得的随机事物。
也许你想要一个动态关闭? 这样的事情在 Common Lisp 中并不存在,尽管它在某些 Lisp 方言中存在(比如 Pico Lisp,据我所知)。
请注意,您可以执行以下类似操作:
不过,我建议您认真考虑一下您是否真的想要这样做。
What is the actual problem that you want to solve? Most likely, you're trying to tackle it the wrong way. Lexical bindings are for things that appear lexically within their scope, not for random stuff you get from outside.
Maybe you want a dynamic closure? Such a thing doesn't exist in Common Lisp, although it does in some Lisp dialects (like Pico Lisp, as far as I understand).
Note that you can do the following, which is similar:
I advise you to think hard about whether you really want this, though.
在 Common Lisp 中,你可以定义 *evalhook* ,它允许您将环境传递给
(eval ...)
。*evalhook*
与平台无关。In Common Lisp you can define *evalhook* Which allows you to pass an environment to
(eval ...)
.*evalhook*
is platform independent.可以使用COMPILE将表达式编译成函数,然后在动态设置变量的环境中使用PROGV对编译后的函数进行FUNCALL。 或者,更好的是,使用 COMPILE 将表达式编译为接受变量的函数。
编译接受函数定义作为列表并将其转换为函数。 在 SBCL 的情况下,该函数被编译为机器代码并且将有效执行。
第一个选项(使用编译和 progv):
第二个选项:
It is possible to use COMPILE to compile the expression into function and then use PROGV to FUNCALL the compiled function in the environment where variables are dynamically set. Or, better, use COMPILE to compile the expression into function that accepts variables.
Compile accepts the function definition as a list and turns it into function. In case of SBCL, this function is compiled into machine code and will execute efficiently.
First option (using compile and progv):
Second option: