在defgeneric中使用:method选项

amp*_*108 6 common-lisp clos

在阅读Keene的书时,我注意到它defgeneric有一个:method选项,它似乎允许你在泛型定义中指定一个方法.我见过的大多数文档都有单独定义的所有适用方法defmethod.该hyperspec,以其一贯的清晰度,列出:method作为一个选项defgeneric,但并没有说是什么意思.

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

Jos*_*lor 8

超常规,其通常的清晰度,列出:方法作为defgeneric的选项,但没有说明它意味着什么.

实际上,defgenericHyperSpec条目,通常清晰,准确地说明了它的含义.它说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通用函数简介很有用:

一些运算符定义泛型函数的方法.这些运算符将被称为方法定义运算符; 它们的相关形式称为方法定义形式.标准化的方法定义运算符在下图中列出.

defgeneric        defmethod  defclass  
define-condition  defstruct
Run Code Online (Sandbox Code Playgroud)