在阅读Keene的书时,我注意到它defgeneric有一个:method选项,它似乎允许你在泛型定义中指定一个方法.我见过的大多数文档都有单独定义的所有适用方法defmethod.该hyperspec,以其一贯的清晰度,列出:method作为一个选项defgeneric,但并没有说是什么意思.
该:method选项是否提供默认值,或者至少是文档,表示您期望最常见的用例,或者它是否具有其他语义?作为一个样式点,如果你希望只定义一个方法,那么在defgeneric表单中定义它是否更有意义(如果你可以,确实这样做),或者单独在一个defmethod?或者在这种情况下制作通用函数没有意义,而是使用常规函数defun?
超常规,其通常的清晰度,列出:方法作为defgeneric的选项,但没有说明它意味着什么.
实际上,defgeneric的HyperSpec条目,通常清晰,准确地说明了它的含义.它说defgeneric的语法是:
defgeneric function-name gf-lambda-list [[option | {方法-描述}*]]
然后说方法描述的语法是:
method-description :: =(:method method-qualifier*specialized-lambda-list [[declaration*| documentation]] form*)
然后它描述了方法组合:
每个方法描述都定义了泛型函数的方法.每个方法的lambda列表必须与gf-lambda-list选项指定的lambda列表一致.如果未指定方法描述且尚不存在同名的通用函数,则会创建不带方法的通用函数.
所以:方法表单用于定义泛型函数的方法,就像defmethod表单一样.
(我将给予它并没有真正说你为什么宁愿defgeneric加任何东西:方法而不是defmethod记住.常见 Common Lisp中意味着该语言是统一大量现有Lisp实现的企图可能.一些支持:方法和其他支持defmethod的方法,这是提供统一界面的最简单方法.)
也就是说,以下内容会产生相同的效果:
(defgeneric to-list (object))
(defmethod to-list ((object t))
(list object))
(defmethod to-list ((object list))
object)
Run Code Online (Sandbox Code Playgroud)
(defgeneric to-list (object)
(:method ((object t))
(list object))
(:method ((object list))
object))
Run Code Online (Sandbox Code Playgroud)
有时可以方便地定义一些方法以及defgeneric表单.这更多的是风格问题,这会涉及到问题的其他部分.
:method选项是否提供了一个默认的,或者至少是文档,您希望最常见的用例是什么,或者它是否具有其他语义?
如果您定义没有类型说明符的方法,或者使用适用于每个对象的类型说明符(例如,t),它可以是一种默认值.
作为一个样式点,如果你希望只定义一个方法,那么以defgeneric形式定义它是否更有意义(如果你可以,确实这样做),或者在defmethod中单独定义它?或者在这种情况下制作通用函数没有意义,而是使用常规的defun?
我认为这取决于你期望只定义一种方法的原因.如果是因为你只是定义一个默认值,但希望其他用户在其上实现方法,那么如果有人需要找到源代码,那么将方法与defmethod一起放置可能会很方便.如果你期望只有一件事要做,那么正常的功能可能更有意义.我认为这些决定只取决于风格选择.
值得注意的是,还有其他形式可以定义泛型函数的方法(以及其他可以生成泛型函数的形式).在HyperSpec中,使用向上箭头转到更高的部分通常会带给你更多的散文.在这种情况下,7.6.1通用函数简介很有用:
一些运算符定义泛型函数的方法.这些运算符将被称为方法定义运算符; 它们的相关形式称为方法定义形式.标准化的方法定义运算符在下图中列出.
Run Code Online (Sandbox Code Playgroud)defgeneric defmethod defclass define-condition defstruct