使用不同参数列表"重载"CLOS多方法

def*_*dle 3 lisp common-lisp clos

我试图在Common Lisp中对多方法进行"重载调用".这是案例的简化纲要:

(defclass foo ()
  ((slotty :accessor slotty :initarg :slotty)))

(defclass bar ()
  ((slotty :accessor slotty :initarg :slotty)))

(defparameter *foo* (make-instance 'foo :slotty "defnoodle"))
(defparameter *bar* (make-instance 'bar :slotty "Chocolate"))

(defmethod contrived ((f foo) (b bar))
  (format t "i pity the foo ~A, who has a bar ~A ~%" (slotty f) (slotty b)))

(contrived *foo* *bar*)
Run Code Online (Sandbox Code Playgroud)

输出: i pity the foo defnoodle, who has a bar Chocolate

但是一旦我尝试定义下一个方法:

 (defmethod contrived ((f foo))
    (format  t "i just pity the foo ~A ~%" (slotty f)))
Run Code Online (Sandbox Code Playgroud)

CL生气了:

; The generic function #<STANDARD-GENERIC-FUNCTION CONTRIVED (1)>
; takes 2 required arguments; was asked to find a method with
; specializers (#<STANDARD-CLASS FOO>)
;   [Condition of type SB-PCL::FIND-METHOD-LENGTH-MISMATCH]
; See also:
;  Common Lisp Hyperspec, FIND-METHOD [:function]
Run Code Online (Sandbox Code Playgroud)

有谁知道我在做错了什么?我知道initialize-instance具有类似的灵活性,因为每个类应该能够为每个类和每个任意数量的参数识别n个初始化实例方法.

(defmethod initialize-instance :after ((f foo) &key)
  ())
Run Code Online (Sandbox Code Playgroud)

但我不清楚如何将其转化为我上面给出的香草例子.而且我觉得我可能会咆哮错误的树,因为这是MOP的一部分.

Rai*_*wig 6

你写道:有谁知道我在做错了什么?

说清楚:CLOS不支持这一点.在单个泛型函数的方法的方法参数列表中,不能有不同数量的必需参数.调度仅适用于所需的参数.Common Lisp不支持'重载'.

INITIALIZE-INSTANCE 使用以下语法定义:

initialize-instance instance &rest initargs &key &allow-other-keys => instance
Run Code Online (Sandbox Code Playgroud)

所有方法都采用一个必需的参数,即实例.仅对此对象执行调度.然后它允许各种关键字参数 - 不为它们进行调度.

因此,您需要就通用函数应该采用的所需参数的数量达成一致,并在代码中以这种方式调用它.

有关规则,请参阅CL Hyperspec:所有通用函数方法的全等Lambda列表.