在阅读Keene的书时,我注意到defgeneric
有一个:method
选项,这似乎允许您在泛型定义中指定一个方法。我见过的大多数文档都包含在单独的defmethod
中定义的所有适用方法。 hyperspec以其通常的清晰度列出:method
作为defgeneric
的选项,但未说明其含义。
:method
选项是否提供了一个默认的,或者至少是文档,您希望最常见的用例是什么,或者它是否具有其他语义?作为样式点,如果您希望仅定义一个方法,那么在defgeneric
形式中定义它(如果可以,确实这样做)或在defmethod
中单独定义更有意义吗? ?或者在这种情况下制作通用函数没有意义,而是使用常规defun
?
答案 0 :(得分:8)
超标准,通常清晰,列出:方法作为选项 defgeneric,但没有说明它意味着什么。
实际上,HyperSpec entry for defgeneric通常清晰明确地说明了它的含义。它说defgeneric的语法是:
defgeneric function-name gf-lambda-list [[option | {方法-描述} *]]
然后说方法描述的语法是:
method-description :: =(:method method-qualifier * specialized-lambda-list [[declaration * | documentation]] form *)
然后它描述了方法组合:
每个方法描述都定义了泛型函数的方法。该 每个方法的lambda列表必须与lambda列表一致 由gf-lambda-list选项指定。如果没有方法描述 指定的和同名的通用函数尚未 存在,创建一个没有方法的泛型函数。
所以:方法表单用于定义泛型函数的方法,就像 defmethod 表单一样。
(我会认为它并没有真正说明为什么你更喜欢defgeneric plus:方法而不是defmethod。请记住共同的 Common Lisp意味着该语言试图统一许多现有的Lisp实现。也许一些支持:方法和其他支持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))
有时可以方便地定义一些方法以及defgeneric表单。这更像是一种风格问题,而这又涉及到问题的其他部分。
:method选项是否提供默认值,或者至少是文档内容 你期望最常见的用例是,或者它有 额外的语义?
如果您定义一个没有类型说明符的方法,或者使用适用于每个对象的类型说明符(例如, t ),它可以是一种默认值。
作为样式点,如果您希望只定义一个方法,那么以defgeneric形式定义它是否更有意义(如果可以, 确实,这样做),或者在defmethod中单独进行?或者它没有 在这种情况下完全使用泛型函数,而不是使用 定期定论?
我认为这取决于您希望仅定义一种方法的原因。如果是因为您只是定义了默认值,但希望其他用户在其上实现方法,那么如果有人需要查找源,那么将方法与defmethod一起放置可能会很方便。如果您希望只做一件事,那么正常的功能可能更有意义。我认为这些决定只取决于风格选择。
还值得注意的是,还有其他形式可以定义泛型函数的方法(以及其他可以生成泛型函数的形式)。在HyperSpec中,使用向上箭头转到更高的部分通常会带给你更多的散文。在这种情况下,7.6.1 Introduction to Generic Functions很有用:
某些运算符定义泛型函数的方法。这些运营商 将被称为方法定义运算符;他们的相关 表单称为方法定义表单。标准化 方法定义运算符列在下图中。
defgeneric defmethod defclass define-condition defstruct
答案 1 :(得分:2)
这取决于个人偏好以及如何在源中组织系统。任
简单的通用函数:一堆DEFMETHODS
复杂的通用函数:DEFGENERIC
和一堆DEFMETHODS
泛型函数:DEFGENERIC
和
CLOS之前的大多数Lisp OO系统使用单一方法定义表单。代码可能在一种形式上变得太长,否则,通用函数大多不存在,...
使用面向类的单调度系统,在类定义中组织方法是有意义的。通过引入泛型函数和多个调度,在通用函数定义下组织它们是有意义的。