5

给定一个内容为 1 的变量,我知道它是至少五种类型的成员:

 1 (let* ((fred 1))
 2   (princ (typep fred 'bit)) (terpri)
 3   (princ (typep fred 'integer)) (terpri)
 4   (princ (typep fred 'fixnum)) (terpri)
 5   (princ (typep fred 'rational)) (terpri)
 6   (princ (typep fred t)) (terpri))
T
T
T
T
T

这里有两个问题。

  1. 给定一个具有任意内容的变量,我如何确定它的超类型路径?

  2. 我在哪里可以在文档中找到答案?

4

2 回答 2

12

类型

你问的是类型,而不是。你不能期望你的问题得到一个好的答案,因为你的号码1所属的类型比你真正关心的要多得多。例如,

(typep 1 '(integer -6 42))
==> T

如果您将注意力限制在Standardized Atomic Type Specifiers上,则可以使用类似

(defconstant *Standardized-Atomic-Type-Specifiers* ...) ; see Figure 4-2
(sort (remove-if-not (lambda (type) (typep 1 type)) 
                     *Standardized-Atomic-Type-Specifiers*)
      #'subtypep)
==> (BIT FIXNUM UNSIGNED-BYTE SIGNED-BYTE INTEGER RATIONAL REAL NUMBER ATOM T)

课程

现在,如果您愿意将兴趣限制在课程上,情况就会变得更易于管理。

首先,CLOS支持多重继承,所以“超类型路径”并不是先验唯一定义的。

但是,它必须被定义以确定方法的优先顺序,并且这个“路径”被称为类优先列表。它由标准MOP函数计算compute-class-precedence-list

(compute-class-precedence-list (class-of 1))
==> (#<BUILT-IN-CLASS INTEGER> #<BUILT-IN-CLASS RATIONAL> #<BUILT-IN-CLASS REAL>
     #<BUILT-IN-CLASS NUMBER> #<BUILT-IN-CLASS T>)

它存在于大多数 Common Lisp 实现中(使用aproposfind-all-symbols查找它是从哪个包导出的)。

您可以使用class-name来获取类的名称而不是它们的元对象:

(mapcar #'class-name (compute-class-precedence-list (class-of 1)))
==> (INTEGER RATIONAL REAL NUMBER T)

请注意,,,,,,不在此列表中bit,因为它们没有命名标准,只是类型fixnumunsigned-bytesigned-byteatom

于 2013-10-13T18:00:59.460 回答
2

这并不容易,IIRC。

我会以某种方式使用 CLOS:

CL-USER 34 > (loop for c = (class-of 1)
                   then (first (class-direct-superclasses c))
                   collect (class-name c)
                   until (eq c (find-class t)))
(FIXNUM INTEGER RATIONAL REAL NUMBER T)

请注意,您需要CLASS-DIRECT-SUPERCLASSESCLOS 实现提供的。

于 2013-10-13T14:04:37.020 回答