我想做的是:
(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
旨在与 CLOS 一起使用,而不是与任意类型说明符一起使用。 Common Lisp 中是否有一个类似于 defgeneric 的系统,它可以为我提供任意类型说明符(而不仅仅是类)所需的行为?
Common Lisp 定义了两个相关但不相同的层次结构:类型层次结构和类层次结构。每个类都是一种类型,但反之则不然——有些类型不是类。例如,integer
and string
是类,因此也是类型。另一方面,(integer 1 *)
and (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)))
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)