Common lisp 在defgeneric中使用:方法选项

Common lisp 在defgeneric中使用:方法选项,common-lisp,clos,Common Lisp,Clos,我注意到,在阅读基恩的书时,defgeneric有一个:method选项,它似乎允许您在泛型定义本身中指定一个方法。我看到的大多数文档都在单独的defmethods中定义了所有适用的方法。以其通常的清晰性,将:方法列为defgeneric的一个选项,但没有说明它的含义 :method选项是否提供了默认值,或者至少记录了您期望的最常见用例,或者它是否具有附加语义?作为一个样式点,如果您希望只定义一个方法,那么在defgeneric表单中定义它(如果您确实可以这样做)或者单独在defmethod中定

我注意到,在阅读基恩的书时,
defgeneric
有一个
:method
选项,它似乎允许您在泛型定义本身中指定一个方法。我看到的大多数文档都在单独的
defmethod
s中定义了所有适用的方法。以其通常的清晰性,将
:方法
列为
defgeneric
的一个选项,但没有说明它的含义

:method
选项是否提供了默认值,或者至少记录了您期望的最常见用例,或者它是否具有附加语义?作为一个样式点,如果您希望只定义一个方法,那么在
defgeneric
表单中定义它(如果您确实可以这样做)或者单独在
defmethod
中定义它更有意义吗?或者,在这种情况下,创建一个泛型函数,而使用常规的
defun
,没有任何意义吗

hyperspec以其通常的清晰性,将:方法列为 定义泛型,但没有说明它的含义

事实上,以其一贯的清晰性,这个词确切地表达了它的意思。它说defgeneric的语法是:

defgeneric函数名gf lambda list[[option |{method description}*]

然后说方法描述的语法是:

方法描述::=(:方法限定符*专用lambda列表[[声明*|文档]]表单*)

然后介绍了方法组合:

每个方法描述在泛型函数上定义一个方法。这个 每个方法的lambda列表必须与lambda列表一致 由gf lambda列表选项指定。如果没有方法说明 已指定,但尚未指定同名的泛型函数 存在时,将创建不带方法的泛型函数

因此:method表单用于定义泛型函数上的方法,就像defmethod表单一样

(我承认它并没有真正说明为什么您更喜欢defgeneric plus:method而不是defmethod。请记住,Common Lisp中的Common意味着该语言试图统一许多现有的Lisp实现。可能有些支持:method,有些支持defmethod,这就是easi提供统一接口的最佳方式。)

也就是说,以下内容具有相同的效果:

(defgeneric to-list (object))

(defmethod to-list ((object t))
  (list object))

(defmethod to-list ((object list))
  object)

有时候,定义一些方法和defgeneric表单是很方便的,这更多的是风格问题,这涉及到问题的其他部分

:方法选项是否表示默认值,或者至少表示文档内容 您希望最常见的用例是,或者它有 附加语义

如果定义的方法没有类型说明符,或者使用适用于每个对象的类型说明符(例如,t),则它可以是一种默认值

作为一个样式点,如果希望只定义一个方法,那么以defgeneric形式定义它是否更有意义(如果可以, 事实上,这样做),或单独在一个defmethod?或它不 在这种情况下,创建泛型函数并使用 一次正式的聚会

我认为这取决于为什么您希望只定义一个方法。如果这是因为您只是定义了一个默认值,但希望其他用户在其上实现方法,那么如果有人需要查找源代码,将这些方法与defmethod放在一起可能会很方便。如果您希望只有一件事要做,那么可以使用正常的函数更合理。我认为这些决定归根结底是风格的选择

还值得注意的是,还有其他表单可以定义泛型函数上的方法(以及其他可以生成泛型函数的表单)。在HyperSpec中,使用向上箭头转到更高的部分通常会让您看到更多的散文。在这种情况下,这一点很有用:

某些运算符定义泛型函数的方法。这些运算符 将被称为方法定义运算符;其关联 表单称为方法定义表单 下一个图中列出了定义运算符的方法

defgeneric        defmethod  defclass  
define-condition  defstruct

这取决于个人偏好以及系统在源代码中的组织方式

  • 简单的泛型函数:一堆
    DEFMETHODS

  • 复杂泛型函数:一个
    DEFGENERIC
    和一堆
    DEFMETHODS

  • 泛型函数:一个
    DEFGENERIC
    和一组内部方法

CLOS之前的大多数Lisp OO系统使用单一方法定义形式。一种形式的代码可能会太长,否则,泛型函数大多不存在


对于面向类的单分派系统,在类定义中组织方法是有意义的。随着泛型函数和多分派的引入,在泛型函数定义下组织方法是有意义的。

CLOS主要基于Flavors/新Flavors和LOOPS/CommonLOOPS。许多方法可以是长的,也可以是长的通常情况下,不喜欢在一个长表单中放置多个。另外,仅用一种方法就可以使重新定义变得更容易/更快…谢谢。也许hyperspec是为眼睛比我好的人设计的。(我不敢相信,当我指的是“它”的时候,我竟然在其中放了一个“它”。)@amp108实际上还有一些其他形式介绍了泛型函数的方法(在某些情况下也介绍了泛型函数)。hyperspec的一些散文部分讨论了这一点;我在最后用一段更新了我的答案。
defgeneric        defmethod  defclass  
define-condition  defstruct