我正在尝试编写一个宏,它会自动为所有插槽写一个类的加速器。我想出了这个
(defmacro defacc (class)
(loop for name in (mapcar #'slot-definition-name
(class-slots (class-of (make-instance `,class))))
do
`(defun ,name (,class)
(slot-value ,class ',name))))
但是它没有定义任何函数(没有循环,它适用于单个函数和单个插槽名称。我不知道问题所在。我还尝试了(class-of (make-instance 'class))
和(class-of ',class)
。没有功能出现。
P.S。我没有忘记用我的班级写这个宏。
答案 0 :(得分:5)
定义个别功能
我们假设您有两种形式定义函数foo
和bar
。
CL-USER 68 > (defun foo (baz) baz)
FOO
CL-USER 69 > (defun bar (baz) baz)
BAR
以一种Lisp形式定义更多功能
现在您想在一个Lisp表单中使用这两个表单。它们的典型方式是使用一个提供表格体的运算符。
progn
就是这样的运营商。其子表单将逐个执行,并返回最后的结果。
CL-USER 70 > (progn
(defun foo (baz) baz)
(defun bar (baz) baz))
BAR
生成PROGN表格
现在假设你有Lisp代码作为数据,这里是一个Lisp表单列表。
CL-USER 71 > '((defun foo (baz) baz)
(defun bar (baz) baz))
((DEFUN FOO (BAZ) BAZ)
(DEFUN BAR (BAZ) BAZ))
要创建有效的progn
表单,您只需将progn
放在列表的前面:
CL-USER 72 > (cons 'progn
'((defun foo (baz) baz)
(defun bar (baz) baz)))
(PROGN
(DEFUN FOO (BAZ) BAZ)
(DEFUN BAR (BAZ) BAZ))
生成PROGN表单的宏
宏需要生成的内容:有效的progn
表单。
生成progn
表单的宏示例:
CL-USER 74 > (defmacro baz (sym)
(cons 'progn
`((defun foo (,sym) ,sym)
(defun bar (,sym) ,sym))))
BAZ
CL-USER 75 > (pprint (macroexpand-1 '(baz fourtytwo)))
(PROGN
(DEFUN FOO (FOURTYTWO) FOURTYTWO)
(DEFUN BAR (FOURTYTWO) FOURTYTWO))
答案 1 :(得分:4)
Defclass
已经有了用于定义访问者,读者和作者的插槽选项:
(defclass foo ()
((bar :accessor foo-bar)))
这与类一起定义了一个专门用于foo-bar
的方法foo
,它返回bar
个插槽的值,以及一个方法setf foo-bar
来编写到那个位置。还有一个:reader
和一个:writer
选项可以单独定义它们。
很多人都围绕defclass
编写了自己的包装器,以使其更加方便(例如,自动使用命名约定)。然而,缺点是本地使用的包装器很可能对其他人不熟悉,并且增加的认知负荷通常不被视为值得进行轻微的便利性改进。
答案 2 :(得分:3)