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

时间:2015-05-27 07:57:45

标签: macros lisp common-lisp sbcl

我定义了以下简单的宏:

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

现在我想在以下功能中使用它:

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

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

当我执行函数创建一个类“myclass”时,我得到了一个类型为“mode”的类的创建:

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

似乎我的论证没有被使用?如何使用函数 create-data 来使用参数?

2 个答案:

答案 0 :(得分:3)

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是要定义的类的名称,而不是您作为参数传递的内容。

您应该使用(define-class myclass)代替(create-data 'myclass)

答案 1 :(得分:2)

我会用这样的东西:

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>

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

相关问题