【问题标题】:Closure inside a Common Lisp MacroCommon Lisp 宏中的闭包
【发布时间】:2019-12-16 20:43:19
【问题描述】:

在下面的代码中,如何让xy 变量反映宏调用时给出的表达式?

(defmacro defrule (init-form &rest replication-patterns)
  (let (rule-table)
   `(destructuring-bind (p x y) ',init-form
       #'(lambda (w h) (list x y)))))

当扩展呼叫时:

(defrule (70 (* 1/2 w) (+ h 3)))

它返回:

(DESTRUCTURING-BIND (P X Y) '(70 (* 1/2 W) (+ H 3))
  #'(LAMBDA (W H) (LIST X Y)))

带有WH 引用的原始表达式丢失。我尝试反引用 lambda 函数创建:

(defmacro defrule (init-form &rest replication-patterns)
  (let (rule-table)
    `(destructuring-bind (p x y) ',init-form
       `#'(lambda (w h) (list ,x ,y)))))

但同样的调用:

(defrule (70 (* 1/2 w) (+ h 3)))

扩展到:

(DESTRUCTURING-BIND
    (P X Y)
    '(70 (* 1/2 W) (+ H 3))
  `#'(LAMBDA (W H) (LIST ,X ,Y)))

返回一个缺点:

#'(LAMBDA (W H) (LIST (* 1/2 W) (+ H 3)))

funcall 不能使用它,并且可以像函数对象一样轻松传递。如何返回一个函数对象,其中包含我作为init-formx y 部分的参数传入的表达式,并且闭包函数可以看到W H 引用?

【问题讨论】:

  • 这似乎是一个糟糕的设计,需要用户知道变量WH是在扩展中生成的。
  • 这是程序内部结构的一部分,不打算供用户使用。在调用这个宏时,W H 变量是未知的,所以我想返回一个函数,稍后当它们可用时可以用明确的W H 调用。

标签: macros common-lisp


【解决方案1】:

你得到了一个缺点,因为你有嵌套的反引号。

destructuring-bind 周围不需要反引号,因为您在宏展开时解构,您可以直接在宏 lambda 列表中进行解构。

(defmacro defrule ((p x y) &rest replication-patterns)
  (let (rule-table)
    `#'(lambda (w h) (list ,x ,y))))

【讨论】:

    【解决方案2】:

    查看您的代码:

    (defmacro defrule (init-form &rest replication-patterns)
      (let (rule-table)
       `(destructuring-bind (p x y) ',init-form
           #'(lambda (w h) (list x y)))))
    

    您想要一个扩展为代码的宏,然后在运行时获取代码并返回一个闭包?

    这可能不是一个好主意。

    请记住:它是宏,它应该在宏扩展时操作代码。在运行时,代码应该是固定的。请参阅 Barmar 对如何改进代码的说明。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-10-27
      • 2013-07-04
      • 1970-01-01
      • 2018-08-21
      • 2013-12-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多