Reputation: 1169
While reading about CLOS (in ANSI Common Lisp by Paul Graham), I noticed that there are nine functions that can be given to defmethod
as its second argument:
+
, and
, append
, list
, max
, min
, nconc
, or
and progn
. According to this answer, they are called simple method combinations.
Why only these nine? What is the reason I cannot pass an arbitrary function as the second argument?
Suppose I defined xor
as
(defun xor (&rest args)
(loop for a in args counting (not (null a)) into truths
finally (return (= truths 1))))
(this could certainly be improved). I would like to define several classes describing clothes and their combinations using xor
:
(defgeneric looks-cool (x)
(:method-combination xor))
(defclass black-trousers () ())
(defclass quilt () ())
(defclass white-shirt () ())
(defclass hawaii-shirt () ())
(defmethod looks-cool xor ((tr black-trousers)) nil)
(defmethod looks-cool xor ((qu quilt)) t)
(defmethod looks-cool xor ((ws white-shirt)) nil)
(defmethod looks-cool xor ((hs hawaii-shirt)) t)
(defclass too-stiff (black-trousers white-shirt) ())
(defclass scottish (quilt white-shirt) ())
(defclass also-good (black-trousers hawaii-shirt) ())
(defclass too-crazy (quilt hawaii-shirt) ())
Now if this compiled (which it doesn't), I would be able to use Lisp to guide me as to what to wear:
> (looks-cool (make-instance 'too-stiff))
NIL
> (looks-cool (make-instance 'scottish))
T
> (looks-cool (make-instance 'also-good))
T
> (looks-cool (make-instance 'too-crazy))
NIL
I am well aware that this is a rather artificial example of no practical importance. Still, I would like to know whether there is some deeper reason behind or whether the restriction to the nine functions is just to make implementation easier.
Upvotes: 2
Views: 443
Reputation: 139261
Use the standard Common Lisp macro DEFINE-METHOD-COMBINATION to define your own simple method combinations:
Example:
(define-method-combination xor :identity-with-one-argument t)
Then:
CL-USER 5 > (mapcar #'looks-cool
(list (make-instance 'too-stiff)
(make-instance 'scottish)
(make-instance 'also-good)
(make-instance 'too-crazy)))
(NIL T T NIL)
If we look at (define-method-combination xor :identity-with-one-argument t)
, it has several meanings for the name xor
:
it uses an operator xor
- a function, macro or special form - not only functions are allowed. If the operator name should be different from the method combination name -> use the :operator
keyword to specify that.
it defines a method combination named xor
. This name can be used in defgeneric
.
it defines a method qualifier xor
. This can be used in defmethod
.
Note that one can also define more complex method combinations with that DEFINE-METHOD-COMBINATION
.
Upvotes: 9