CLOS:与任意函数组合的方法

Dom*_*riš 2 oop language-design common-lisp clos method-combination

一边念叨CLOS(在ANSI Common Lisp的由保罗·格雷厄姆),我注意到,有一些可以给九项职能defmethod作为其第二个参数: +,and,append,list,max,min,nconc,orprogn.根据这个答案,它们被称为简单方法组合.

为什么只有这九个?我不能将任意函数作为第二个参数传递的原因是什么?

我想要的例子

假设我定义xor

(defun xor (&rest args)
   (loop for a in args counting (not (null a)) into truths
      finally (return (= truths 1))))
Run Code Online (Sandbox Code Playgroud)

(这当然可以改善).我想用以下方法定义描述衣服及其组合的几个类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) ())
Run Code Online (Sandbox Code Playgroud)

现在如果这个编译(它没有),我将能够使用Lisp指导我穿什么:

> (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
Run Code Online (Sandbox Code Playgroud)

我很清楚这是一个没有实际意义的人为例子.不过,我想知道是否存在一些更深层次的原因,或者对九个函数的限制是否只是为了使实现更容易.

Rai*_*wig 6

使用标准Common Lisp宏DEFINE-METHOD-COMBINATION定义您自己的简单方法组合:

例:

(define-method-combination xor :identity-with-one-argument t)
Run Code Online (Sandbox Code Playgroud)

然后:

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)
Run Code Online (Sandbox Code Playgroud)

如果我们看一下(define-method-combination xor :identity-with-one-argument t),它有几个含义xor:

  • 它使用运算符 xor - 函数,宏或特殊形式 - 不仅允许函数.如果运算符名称应与方法组合名称不同 - >使用:operator关键字指定该名称.

  • 它定义了一个名为的方法组合xor.这个名字可以用在defgeneric.

  • 它定义了一个方法限定符 xor.这可以用于defmethod.

请注意,还可以使用它定义更复杂的方法组合DEFINE-METHOD-COMBINATION.