Question

I am trying to do an "overload call" of a multimethod in Common Lisp. Here is a simplified rundown of the case:

(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*)

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

But as soon as I try to define the next method:

 (defmethod contrived ((f foo))
    (format  t "i just pity the foo ~A ~%" (slotty f)))

CL gets mad:

; 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]

Does anyone know what I am doing wrong here? I know that initialize-instance has a similar kind of flexibility since one should be able to identify n number of initialize-instance methods per class and per any number of arguments.

(defmethod initialize-instance :after ((f foo) &key)
  ())

but it is not clear to me how I can translate this to the vanilla example I gave above. And I feel like I could be barking up the wrong tree since this is part of MOP.

Was it helpful?

Solution

You write: Does anyone know what I am doing wrong here?

To make it clear: CLOS does not support that. You can't have different numbers of required arguments in method parameter lists of methods of a single generic function. Dispatching works over the required arguments only. Common Lisp does not support 'overloading'.

INITIALIZE-INSTANCE is defined with this syntax:

initialize-instance instance &rest initargs &key &allow-other-keys => instance

All methods take one required argument, the instance. Dispatching is only done over this object. It then allows various keyword arguments - no dispatching is done for them.

So you need to agree on the numbers of required arguments your generic function should take and call it that way in your code.

See the CL Hyperspec for the rules: Congruent Lambda-lists for all Methods of a Generic Function.

OTHER TIPS

All methods of a generic function must have a congruent argument list. Argument lists are congruent if you have the same number of required arguments, the same number of optional arguments, and use &rest and &key in a compatible way.

But, of course, you cannot specialize by the types of the &optional, &rest or &key arguments.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top