From: Mario Tanev
Subject: Re: defgeneric, defstruct and no CLOS
Date: 
Message-ID: <kW3af.8865$q%.3659@newssvr12.news.prodigy.com>
That is not necessarily a problem, since a generic is allowed to take a
variable number of parameters. Here's how to go around that:

;; super-class
(defclass parent () ())

;; sub-class
(defclass child (parent) ())

;; mystery defined on parent (1 parameter version
(defmethod mystery ((object parent) &rest args)
  (apply #'(lambda (x) (not x)) args))

;; mystery defined on child
(defmethod mystery ((object child) &rest args)
  (apply #'(lambda (x y) (+ x y)) args))

;; inherited? _only_ defined on parent
(defmethod inherited? ((object parent) &rest args)
  (apply #'(lambda () (format t "Answer: It was defined on class parent
~%" )) args))

(defparameter pobj (make-instance 'parent))
(defparameter cobj (make-instance 'child)) 

;; Here we call mystery with 1 parameter
(format t "(mystery pobj nil) -> ~A~%" (mystery pobj nil))

;; Here we call mystery with 2 parameters
(format t "(mystery cobj 2 3) -> ~A~%" (mystery cobj 2 3))

(format t "Question: Where was inherited defined for pobj? ")
(inherited? pobj)
(format t "Question: Where was inherited defined for cobj? ")
(inherited? cobj)

;; So what is this clunkyness with apply/lambda
;; Well, we can avoid it with macros
;; Unfortunately it only specializes on the first parameter
(defmacro defvirtual (name ((object class) &rest formals) &rest body)
  `(defmethod ,name ((,object ,class) &rest args)
     (apply #'(lambda ,formals ,@body) args)))

;; Now let's try it again
(defvirtual myth ((object parent) x)
  (not x))

(defvirtual myth ((object child) x y)
  (+ x y))

;; Here we call myth with 1 parameter
(format t "(myth pobj nil) -> ~A~%" (myth pobj nil))

;; Here we call myth with 2 parameters
(format t "(myth cobj 2 3) -> ~A~%" (myth cobj 2 3))

Homework:
Is there a way to call myth with 1 parameter on cobj and have it invoke the
pobj version? Modify defvirtual to achieve that. Even better, make
defvirtual optionally specialize on more than one parameter. 

And just a note, you don't need defmethod or defgeneric at all, you can
create your own macros that operate on hash tables of "methods" and achieve
the functionality *you* need.

Jack Unrue wrote:

> 
> As a practical matter, I'm saying that the different variations would
> not necessarily be congruent, and that is going to prevent defining
> this method in the way that I think you are intending.  Whereas,
> within problem a domain, you probably will find that there is a
> class hierarchy where such methods would naturally be congruent.
>