任意类型说明符上的Defmethod? [英] Defmethod on Arbitrary Type Specifiers?

查看:30
本文介绍了任意类型说明符上的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定义了两个相关但不完全相同的层次结构:类型层次结构和类层次结构。每个类都是类型,但反之亦然-有些类型不是类。例如,integerstring是类,因此也是类型。另一方面,(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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆