CLOS:方法与任意函数的组合
CLOS: Method combination with arbitrary function
在阅读 CLOS(在 Paul Graham 的 ANSI Common Lisp 中)时,我注意到有九个函数可以作为第二个参数提供给 defmethod
:
+
、and
、append
、list
、max
、min
、nconc
、or
和 progn
。根据this answer,它们被称为简单方法组合。
问题
为什么只有这九个?我不能将任意函数作为第二个参数传递的原因是什么?
我想要的示例
假设我将 xor
定义为
(defun xor (&rest args)
(loop for a in args counting (not (null a)) into truths
finally (return (= truths 1))))
(这当然可以改进)。我想用 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) ())
现在如果编译了(它没有),我将能够使用 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
我很清楚这是一个没有实际意义的相当人为的例子。还是想知道是不是有更深层次的原因,还是限制9个功能只是为了方便实现。
使用标准的 Common Lisp 宏 DEFINE-METHOD-COMBINATION 定义您自己的简单方法组合:
示例:
(define-method-combination xor :identity-with-one-argument t)
然后:
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)
如果我们看(define-method-combination xor :identity-with-one-argument t)
,名字xor
有几个意思:
它使用了一个运算符 xor
- 函数、宏或特殊形式 - 不仅允许函数。如果运算符名称应不同于方法组合名称 -> 使用 :operator
关键字指定。
它定义了一个名为 xor
的 方法组合 。此名称可用于defgeneric
.
它定义了一个方法限定符 xor
。这个可以用在defmethod
.
请注意,还可以定义更复杂的方法组合 DEFINE-METHOD-COMBINATION
。
在阅读 CLOS(在 Paul Graham 的 ANSI Common Lisp 中)时,我注意到有九个函数可以作为第二个参数提供给 defmethod
:
+
、and
、append
、list
、max
、min
、nconc
、or
和 progn
。根据this answer,它们被称为简单方法组合。
问题
为什么只有这九个?我不能将任意函数作为第二个参数传递的原因是什么?
我想要的示例
假设我将 xor
定义为
(defun xor (&rest args)
(loop for a in args counting (not (null a)) into truths
finally (return (= truths 1))))
(这当然可以改进)。我想用 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) ())
现在如果编译了(它没有),我将能够使用 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
我很清楚这是一个没有实际意义的相当人为的例子。还是想知道是不是有更深层次的原因,还是限制9个功能只是为了方便实现。
使用标准的 Common Lisp 宏 DEFINE-METHOD-COMBINATION 定义您自己的简单方法组合:
示例:
(define-method-combination xor :identity-with-one-argument t)
然后:
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)
如果我们看(define-method-combination xor :identity-with-one-argument t)
,名字xor
有几个意思:
它使用了一个运算符
xor
- 函数、宏或特殊形式 - 不仅允许函数。如果运算符名称应不同于方法组合名称 -> 使用:operator
关键字指定。它定义了一个名为
xor
的 方法组合 。此名称可用于defgeneric
.它定义了一个方法限定符
xor
。这个可以用在defmethod
.
请注意,还可以定义更复杂的方法组合 DEFINE-METHOD-COMBINATION
。