7

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

该选项是否:method提供默认值,或者至少记录您期望最常见的用例是什么,或者它是否具有额外的语义?作为一个风格点,如果您希望只定义一个方法,那么在表单中定义它是否更有意义defgeneric(如果您确实可以这样做),还是在defmethod? 或者在这种情况下创建一个通用函数根本没有意义,而是使用一个常规的defun

4

2 回答 2

8

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
于 2015-04-15T02:59:17.110 回答
2

这取决于个人喜好以及系统在源代码中的组织方式。任何一个

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

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

  • 泛型函数:一个DEFGENERIC和一堆方法里面

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

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

于 2015-04-15T13:48:28.527 回答