Lisp常见类型与类的区别

dav*_*ugh 2 types class common-lisp

Common Lisp类层次结构的文章中,Rainer Joswig和Joshua Taylor仔细区分了内置Common Lisp 类型之间的一些区别,其中类构成对基线的CLOS扩展的一部分。类型/类(加上拖把)的区别也反映在Pfeil的综合层次结构图中。使用该图,似乎可以提取两个不同的层次结构。特别是,我目前对层次结构的顶层最感兴趣;即,t(由于t既是类型又是类)的直接子类型和子类。以下是从图中提取的一些临时子类型/子类:

对于类型层次,直接亚型t似乎是atomcharacterrandom-statehash-tablerestartreadtablepackagepathnamestreamfunctionarraysequencenumber,和condition。所有其他类型都喜欢float或是list这些类型之一的子类型。类型层次结构也不严格是层次结构(因为(subtype t t) => T,但这似乎是唯一的例外)。(ps:类型symbolstructure-object并且未包含在图中,但也可能是的直接子类型t。)

对于类层次结构,的直接子类t包括上述所有类型的对应类(除外atom,也许structure-object现在是standard-object(?)的子类),再加上standard-object

MOP通过添加类metaobject(以及一些元子类)来扩展CLOS ,但似乎并未添加到的直接子类中t

有人可以验证这种理解是否正确,还是可以提供其他说明?

注意:我在上面的类型层次结构描述中发现了至少一个错误。所有列出的子类型(character等)显然都是的子类型atom,因此它们不是的直接子类型t。的唯一其他直接亚型t似乎是sequence,因为序列可以是cons(非原子)。而且,symbol实际上,它包含在图中,并且也是的子类型atom

Rai*_*wig 6

在LispWorks中绘制T的CL子类型

查找子类型:

(defun find-synonym-types (type1 types)
  (remove-if-not (lambda (type2)
                   (and (not (eq type1 type2))
                        (subtypep type1 type2)
                        (subtypep type2 type1)))
                 types))

(defun find-all-types-in-packages (packages &key include-nil)
  (let ((types nil))
    (loop for package in packages
          when (find-package package)
          do (do-external-symbols (sym (find-package package))
               (when (ignore-errors (subtypep sym t))
                 (let ((synonyms (find-synonym-types sym types)))
                   (if synonyms
                       (pushnew sym (get (first synonyms) :type-synonyms))
                     (pushnew sym types))))))
    (if include-nil types (remove nil types))))

(defun direct-subtypes (supertype &key all-types)
  (loop with subtypes = (remove supertype (loop for type in all-types
                                                when (subtypep type supertype)
                                                collect type))

        for type in subtypes
        when (loop for type2 in (remove type subtypes)
                   never (subtypep type type2))
        collect type))
Run Code Online (Sandbox Code Playgroud)

绘制它:

#+capi
(defun class-color (class-name)
  (typecase (find-class class-name)
    (standard-class  :blue)
    (built-in-class  :violet)
    (structure-class :brown)
    (otherwise       :red)))

#capi
(defun graph-subtypes-from-t ()
  (let ((all-types (find-all-types-in-packages '("CL" "CLOS"))))
    (capi:contain
     (make-instance
      'capi:graph-pane
      :roots '(t)
      :children-function (lambda (type)
                           (direct-subtypes type :all-types all-types))
      :node-pane-function #'(lambda (graph-pane node)
                              (declare (ignore graph-pane))
                              (make-instance
                               'capi:item-pinboard-object
                               :text (format
                                      nil "~{~a~^, ~}"
                                      (cons node
                                            (get node :type-synonyms)))
                               :graphics-args `(:foreground
                                                ,(if (find-class node
                                                                 nil)
                                                     (class-color node)
                                                   :black))))
      :edge-pane-function #'(lambda (self from to)
                              (declare (ignore self from to))
                              (make-instance
                               'capi:arrow-pinboard-object
                               :graphics-args '(:foreground
                                                :grey))))
     :title "Common Lisp Subtypes in LispWorks")))
Run Code Online (Sandbox Code Playgroud)

图形

具有相应CLOS类的类型以蓝色编写,而结构类为棕色。NIL未绘制类型。包括来自CLOS MOP的类型/类。某些类型具有多个名称。还要注意,该图特定于LispWorks,尤其是实际上哪些类型也是结构,CLOS类,内置类或其他类型。

使用LispWorks在Common Lisp中命名类型

  • 注意,这仅包括由单个符号命名的那些类型。 (2认同)
  • @RainerJoswig,一个非常好用的图表的极好的答案! (2认同)