【问题标题】:Creating a lambda from an s-expression从 s 表达式创建 lambda
【发布时间】:2008-10-19 02:04:54
【问题描述】:

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

(defvar x '(+ a 2))

现在我想创建一个函数,当调用它时,它会在定义它的范围内评估表达式。我试过这个:

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

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

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

编辑:那么,如果 EVAL 问题没有解决方案,还能怎么办?

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

【问题讨论】:

  • 你从哪里得到内部表达式?除非您是从外部源读取它,否则您可以尝试使用宏而不是 eval。
  • 我正在从外部来源阅读它。

标签: lisp lambda eval common-lisp closures


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

    CLISP 实现了一个扩展来评估词法环境中的表单。从它是一个扩展的事实来看,我怀疑你不能以符合标准的方式做到这一点。

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

    http://clisp.cons.org/impnotes.html#eval-environ

    【讨论】:

      【解决方案3】:

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

      也许您想要一个动态闭包? Common Lisp 中不存在这样的东西,尽管它在某些 Lisp 方言中存在(据我所知,比如 Pico Lisp)。

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

      (defvar *a*)
      (defvar *x* '(+ *a* 2))  ;'
      
      (let ((a 10))
        ;; ...
        (let ((*a* a))
          (eval *x*)))
      

      不过,我建议你认真考虑一下你是否真的想要这个。

      【讨论】:

        【解决方案4】:

        在 Common Lisp 中,您可以定义 *evalhook*,它允许您将环境传递给 (eval ...)*evalhook* 独立于平台。

        【讨论】:

        • 非常正确,好像被ANSI删除了
        【解决方案5】:

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

        Compile 将函数定义作为列表接受并将其转换为函数。在SBCL的情况下,这个函数被编译成机器码并且会高效地执行。

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

        (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
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多