问题
Greg Pfeil's Class Hierarchy diagram provides a comprehensive picture the Common Lisp type system. But I'm trying to better understand the class relationships at the top of the hierarchy. For a simple example, let (defstruct person name age)
, and then (defparameter *p1* (make-person :name "Yosh" :age 19)
. Now
(typep *p1* 'person)
T
(typep *p1* 'structure)
T
(typep *p1* 'structure-object)
T
(typep *p1* 'atom)
T
(typep *p1* t)
T
The Hyperspec says the precedence list for
structure-object
is only itself andt
. Areatom
andstructure
not types in the hierarchy?What are all the direct subtypes of
t
? More generally, how can you retrieve all the direct subtypes or supertypes of any given type (without trial-and-errorsubtypep
)? Alternately, is there a way to iterate over a list of all types? Does the MOP offer functions to get at all sub-/super-classes?By analogy with set theory, it would seem that all Common Lisp types/classes could theoretically be subdivided into two subclasses of
t
; namely,standard-object
(corresponding to elements with instances like the number 3, the string "abc", the structure s1, the method m1, etc.), andstandard-class
(corresponding to sets with instances like the classstandard-object
, the classnumber
, the classstructure-object
, etc.). If this is not the actual subdivision oft
, does the reason have something to do with practical implementation; for example, avoiding recursive class relationships in the hierarchy?
回答1:
Types and classes are two different things.
Don't confuse them.
Some types have corresponding classes. Most have not.
atom
is the name of a type, but not of a class.
CL-USER 18 > (find-class 'atom nil)
NIL
Since atom
is not a class, it can't be in any class precedence list.
Thus atom
is not in the class precedence list of structure-object
.
The type structure
is non-standard and not defined by ANSI CL.
Types are not in a class precedence list, classes are.
The interface for types:
- create a type ->
DEFTYPE
- is something of a type? ->
TYPEP
- is a type a subtype of another type? ->
SUBTYPEP
- what is a type for something? ->
TYPE-OF
That's basically all you can do with types.
CLOS classes have corresponding types
CLOS functions and class precedence lists don't work with types, but classes have corresponding types.
CL-USER 23 > (defclass bar () ())
#<STANDARD-CLASS BAR 40200A2413>
CL-USER 24 > (typep (make-instance 'bar) 'bar)
T
CL-USER 25 > (type-of (make-instance 'bar))
BAR
CL-USER 26 > (class-of (make-instance 'bar))
#<STANDARD-CLASS BAR 40200A2413>
CLOS works with classes. Thus in an extended CLOS you can ask for subclasses and superclasses. But not for subtypes or supertypes.
History: Types and CLOS
Common Lisp started in CLtL1 with types and no CLOS.
CLOS and CLOS classes have been added years later. They have been added in such a way that some types got corresponding classes and such that classes have corresponding types.
Common Lisp allows to define types using type specifiers like AND
, OR
, SATISFIES
, MEMBER
, NOT
, ... For those no corresponding CLOS classes exist.
There are also compound type specifiers like (integer 0 100)
. There are also no corresponding CLOS classes for those types.
CL-USER 31 > (deftype integer100 () '(integer 0 100))
INTEGER100
CL-USER 32 > (find-class 'integer100)
Error: INTEGER100 is not the name of a class
回答2:
All classes are types, but not all types are classes. Some types are defined in terms of other types. An atom is anything that's not a cons. Since an instance of a structure isn't a cons, it's an atom. From the HyperSpec:
Type ATOM
Supertypes:
atom, t
Description:
It is equivalent to
(not cons)
.
As another common example, consider the type list, which is equivalent to (or null cons). NIL (of type null) is a list, and a cons is a list. That's it.
Neither atom nor list are classes, but they are types.
Because we can have complement types and union types and intersection types, the concept of type hierarchies gets a bit more complicated, even if there are still proper class hierarchies.
The Hyperspec says the precedence list for structure-object is only itself and t. Are atom and structure not types in the hierarchy?
That's not quite what the HyperSpec says. The HyperSpec says that t is a supertype of structure-type. In Common Lisp, you can define arbitrary new types. E.g., with a simple (deftype my-new-type (or structure-object list)), you'd have (typep *p1* 'my-new-type) return true as well. That doesn't suddenly invalidate what the HyperSpec says about the class precedence of structure-object.
By analogy with set theory, it would seem that all Common Lisp types/classes could theoretically be subdivided into two subclasses of t
That would be one way of doing it, but because of the ability to define new types in terms of union of types, intersection of types, and complements of types, there are many ways that you could partition the objects of Common Lisp by type.
来源:https://stackoverflow.com/questions/42514204/common-lisp-class-hierarchy