Common Lisp class hierarchy

2019-04-14 02:49发布

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
  1. The Hyperspec says the precedence list for structure-object is only itself and t. Are atom and structure not types in the hierarchy?

  2. 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-error subtypep)? 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?

  3. 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.), and standard-class (corresponding to sets with instances like the class standard-object, the class number, the class structure-object, etc.). If this is not the actual subdivision of t, does the reason have something to do with practical implementation; for example, avoiding recursive class relationships in the hierarchy?

2条回答
太酷不给撩
2楼-- · 2019-04-14 03:11

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.

查看更多
放荡不羁爱自由
3楼-- · 2019-04-14 03:27

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
查看更多
登录 后发表回答