Sil*_*olo 5 lisp types common-lisp
我想要做的是这样的:
(defgeneric fn (x))
(defmethod fn ((x (integer 1 *)))
"Positive integer")
(defmethod fn ((x (integer * -1)))
"Negative integer")
Run Code Online (Sandbox Code Playgroud)
我想一个通用的函数,任意类型说明符,包括基于列表的的,如工作(and x y),(or x y),(satisfies p),等.现在,当我试图运行上面的代码,我得到一个"无效的专用函数"的错误.一些研究表明,defgeneric它设计用于CLOS,而不是任意类型说明符.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>
Run Code Online (Sandbox Code Playgroud)
参数专精 - 您在参数之后放置的内容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
Run Code Online (Sandbox Code Playgroud)
如果你真的需要你的代码是模块化的,你需要首先将你的值分类为可以成为特权者的东西,然后发送:
(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)))
Run Code Online (Sandbox Code Playgroud)
没有像 CLOS那样可以提供这样的功能.
它实际上也不适合CLOS.想想以下内容,我们对以下函数进行了以下调用:
(generic-function-foo 2)
Run Code Online (Sandbox Code Playgroud)
现在我们为以下类型定义了方法:
(integer 0 9)
(integer 1 9)
(integer 0 99)
(integer 1 99)
(integer -1000 1000)
(or (satisfies evenp) (integer 0 30))
(satisfies evenp)
(satisfies divisible-by-two)
(satisfies all-numbers-which-are-in-my-list-of-numbers)
Run Code Online (Sandbox Code Playgroud)
所有匹配2的方法应该运行哪个?如果我打电话CALL-NEXT-METHOD,哪一个会是下一个?
现在我们可以说在源代码中按顺序排序.但是在Common Lisp中,您可以在运行时添加,删除或重新定义方法.这种行为或多或少是随机的.
我们需要一些其他冲突解决方案.例如:
已经尝试向CLOS提供更具表现力的调度.但是我不知道向CLOS添加类型.请参阅谓词调度和过滤调度.
除此之外,我会寻找一个基于规则的系统,但这通常与CLOS(Common Lisp对象系统)非常不同,除非它以某种方式集成.