【问题标题】:Defmacro that expands to defsetf扩展为 defsetf 的 Defmacro
【发布时间】:2015-01-30 20:52:48
【问题描述】:

我在 CL 中遇到一些嵌套反引号的问题。我正在尝试创建一个宏define-access,它采用两个参数FAdefine-access 应该为符号 F 定义一个函数和 setf 扩展,其作用类似于 A 的相应函数和 setf。当前代码如下。

(defmacro define-access (F A)
  (let ((X (gensym))
        (Y (gensym)))
    `(progn
       (defun ,F (,X)
         (,A ,X))
       (defsetf ,F (,X) (,Y)
         `(setf (,A ,,X) ,,Y)))))

问题出现在底部,嵌套的反引号。

define-access 的期望行为如下。

(define-access fname car)
=> (progn (defun fname (x) (car x))
          (defsetf fname (x) (y) `(setf (first ,x) ,y)))

但是现在,根据macroexpand-1,我得到以下信息(为理智添加了换行符)。

(PROGN (DEFUN FNAME (#:G22490) (CAR #:G22490))
       (DEFSETF FNAME (#:G22490) (#:G22491)
           (LIST 'SETF (LIST A #:G22490) #:G22491)))

我对反引号运算符有什么不明白的地方,或者我应该如何解决这类问题?

【问题讨论】:

  • 您知道define-accessdefsetf 的缩写形式相同,对吧? (defsetf fname car)
  • 仅供参考,使用宏的方法是 (define-access fname car) 而不是 (define-access (fname car))
  • @Barmar 对,对不起。解决了这个问题。幸运的是,扩展是正确的。
  • @Barmar 是吗? defsetf(据我所知)定义了一个在 getter 上使用 setf 时调用的 write 函数,而不是同义词(即 (defsetf car rplaca) 将定义接近 car 的 setf 的东西)
  • 对不起,你是对的。

标签: macros lisp common-lisp backticks


【解决方案1】:

在嵌套的反引号中 A 之前需要另一个逗号,因此它会扩展为外部反引号之外的变量值。然后需要引用它以防止将其评估为变量。于是就变成了,',A

(defmacro define-access (F A)
  (let ((X (gensym))
        (Y (gensym)))
    `(progn
       (defun ,F (,X)
         (,A ,X))
       (defsetf ,F (,X) (,Y)
         `(setf (,',A ,,X) ,,Y)))))

DEMO

【讨论】:

  • 嗯...这似乎更接近我正在寻找的内容,但是在尝试使用 setf 扩展器时我得到“变量 CAR 没有价值”。
  • 修复它。使用您的新编辑,它可以完美运行。非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多