如何在宏调用中使用参数?

How to use a parameter in a macro call?

我定义了以下简单的宏:

 (defmacro define-class (class-name)
  `(defclass ,class-name ()()))

现在我想在以下函数中使用它:

(defun create-data (mode)
  (define-class mode))

编译最后一个函数后,我得到以下消息,变量 MODE 已定义但从未使用过

当我执行创建 class "myclass" 的函数时,我反而创建了 class 类型 "mode":

 (create-data 'myclass)
 #<STANDARD-CLASS MODE>

好像我的说法没有用?如何让函数 create-data 使用参数?

defclass 不是函数而是宏。它使用源代码中提供的名称(在您的情况下为模式),它与您的变量 mode 不同。事实上,某些 CL 实现会警告您从未使用过参数 mode

您可以对其进行宏扩展 (macroexpand '(defclass mode ()())) 以检查它在您的实现中变成了什么。我在 CLISP 中得到了这个(我稍微清理了一下):

(progn
  (eval-when (compile load eval)
    (apply #'ensure-class 
           'mode ; notice mode is quoted
           :direct-superclasses (list) 
           :direct-slots (list) 
           :metaclass clos::<standard-class>
           (append '(:fixed-slot-locations nil) 
                    (list :direct-default-initargs nil 
                          :documentation nil 
                          :generic-accessors 't))))
  (find-class 'mode)) ; notice mode is quoted

扩展依赖于实现,但结果都是一样的。 mode 是正在定义的 class 的名称,而不是您作为参数传递的名称。

您应该使用 (define-class myclass) 而不是 (create-data 'myclass)

我会用这样的东西:

CL-USER 86 >  (defmacro define-class (class-name)
                `(defclass ,class-name ()()))
DEFINE-CLASS

CL-USER 87 > (defun create-data (mode)
               (funcall (compile nil `(lambda ()
                                        (define-class ,mode)))))
CREATE-DATA

CL-USER 88 > (create-data 'bar)
#<STANDARD-CLASS BAR 402016CC73>

以上使用代码生成和内置编译器。