hyperspec 以其通常的清晰度将 :method 列为 defgeneric 的一个选项,但没有说明它的含义。
实际上,defgeneric的HyperSpec 条目以其通常的清晰度,准确地说明了它的含义。它说 defgeneric 的语法是:
defgeneric 函数名 gf-lambda-list [[option | {方法描述}*]]
然后说方法描述的语法是:
method-description::= (:method method-qualifier* special-lambda-list [[declaration* | documentation]] form*)
然后它描述了方法组合:
每个方法描述都在泛型函数上定义了一个方法。每个方法的 lambda 列表必须与 gf-lambda-list 选项指定的 lambda 列表一致。如果没有指定方法描述并且不存在同名的泛型函数,则创建一个没有方法的泛型函数。
所以 :method 形式用于在泛型函数上定义方法,就像defmethod形式一样。
(我承认它并没有真正说明为什么您更喜欢 defgeneric plus :method 而不是 defmethod。请记住,Common Lisp 中的Common意味着该语言试图统一许多现有的 Lisp 实现。也许一些支持 :method 和其他支持 defmethod,这是提供统一接口的最简单方法。)
也就是说,以下将具有相同的效果:
(defgeneric to-list (object))
(defmethod to-list ((object t))
(list object))
(defmethod to-list ((object list))
object)
(defgeneric to-list (object)
(:method ((object t))
(list object))
(:method ((object list))
object))
有时将一些方法与定义通用形式一起定义会很方便。这更多的是风格问题,这会涉及您问题的其他部分。
:method 选项是否提供默认值,或者至少记录您期望最常见的用例是什么,或者它是否具有额外的语义?
如果您定义一个没有类型说明符的方法,或者使用适用于每个对象的类型说明符(例如t),它可以是一种默认值。
作为一个风格点,如果您希望只定义一个方法,那么以 defgeneric 形式定义它(如果您确实可以这样做)或在 defmethod 中单独定义它更有意义吗?或者在这种情况下创建一个通用函数根本没有意义,而是使用常规的defun?
我认为这取决于您为什么希望只定义一种方法。如果是因为您只是定义了一个默认值,但希望其他用户在其上实现方法,那么如果有人需要查找源代码,将这些方法与 defmethod 一起放置可能会很方便。如果您期望只有一件事要做,那么普通功能可能更有意义。我认为这些决定归结为风格选择。
还值得注意的是,还有其他形式可以在泛型函数上定义方法(以及其他可以产生泛型函数的形式)。在 HyperSpec 中,使用向上箭头转到更高的部分通常会带给您更多的散文。在这种情况下,7.6.1 Introduction to Generic Functions很有用:
一些运算符为泛型函数定义方法。这些运算符将被称为方法定义运算符;它们的关联形式称为方法定义形式。下图中列出了标准化的方法定义运算符。
defgeneric defmethod defclass
define-condition defstruct