Defmacro扩展到defsetf

时间:2015-01-30 20:52:49

标签: macros lisp common-lisp backticks

我在CL中遇到了一些嵌套反引号的问题。我尝试创建一个带有两个参数define-accessF的宏Adefine-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)))

我不了解反引号运算符,或者我该如何处理这类问题?

1 个答案:

答案 0 :(得分:3)

在嵌套反引号中,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