在defgeneric中使用:method选项

时间:2015-04-15 00:26:41

标签: common-lisp clos

在阅读Keene的书时,我注意到defgeneric有一个:method选项,这似乎允许您在泛型定义中指定一个方法。我见过的大多数文档都包含在单独的defmethod中定义的所有适用方法。 hyperspec以其通常的清晰度列出:method作为defgeneric的选项,但未说明其含义。

:method选项是否提供了一个默认的,或者至少是文档,您希望最常见的用例是什么,或者它是否具有其他语义?作为样式点,如果您希望仅定义一个方法,那么在defgeneric形式中定义它(如果可以,确实这样做)或在defmethod中单独定义更有意义吗? ?或者在这种情况下制作通用函数没有意义,而是使用常规defun

2 个答案:

答案 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系统使用单一方法定义表单。代码可能在一种形式上变得太长,否则,通用函数大多不存在,...

使用面向类的单调度系统,在类定义中组织方法是有意义的。通过引入泛型函数和多个调度,在通用函数定义下组织它们是有意义的。