任意类型说明符上的Defmethod? [英] Defmethod on Arbitrary Type Specifiers?
本文介绍了任意类型说明符上的Defmethod?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我尝试做的是:
(defgeneric fn (x))
(defmethod fn ((x (integer 1 *)))
"Positive integer")
(defmethod fn ((x (integer * -1)))
"Negative integer")
我想要一个可以处理任意类型说明符的泛型函数,包括基于列表的说明符,如(and x y)
、(or x y)
、(satisfies p)
等。现在,当我尝试运行上面的代码时,我收到一个"Invalid Specializer"错误。稍微研究一下,就会发现defgeneric
是设计用来处理CLO的,而不是用任意类型说明符的。Common Lisp中是否有一个类似defGeneric的系统可以为任意类型说明符(而不仅仅是类)提供我想要的行为?
推荐答案
Common Lisp定义了两个相关但不完全相同的层次结构:类型层次结构和类层次结构。每个类都是类型,但反之亦然-有些类型不是类。例如,integer
和string
是类,因此也是类型。另一方面,(integer 1 *)
和(satisfies evenp)
是类型,但不是类。
> (type-of "toto")
(SIMPLE-BASE-STRING 4)
> (class-of "toto")
#<BUILT-IN-CLASS STRING>
参数专用符-您在defmethod
中放在参数后面的内容-只能是类名(或形式为(eql value)
)。因为(integer 1 *)
不是类名,所以Common Lisp不允许您的代码。这有一个很好的理由:编译器总是能够确定类层次结构,而类型语言太强大了,无法做到这一点:
(defun satisfies-the-collatz-conjecture (n)
(cond
((<= n 1) t)
((evenp n) (satisfies-the-collatz-conjecture (/ n 2)))
(t (satisfies-the-collatz-conjecture (+ 1 (* n 3))))))
(subtypep 'integer '(satisfies satisfies-the-collatz-conjecture))
NIL ;
NIL
如果您确实需要代码模块化,则需要首先将您的值分类为可以做成专门化的值,然后再对其进行调度:
(defmethod fn-generic (x (sign (eql 'positive)))
"Positive integer")
(defmethod fn-generic (x (sign (eql 'negative)))
"Negative integer")
(defun classify (x)
(cond
((< x 0) 'negative)
((= x 0) 'null)
((> x 0) 'positive)))
(defun fn (x)
(fn-generic x (classify x)))
这篇关于任意类型说明符上的Defmethod?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文