Common Lisp the Language, 2nd Edition
![]()
Next: Specific Data Type
Up: Data Type Predicates
Previous: Data Type
Predicates
If a data type is viewed as the set of all objects belonging to the
type, then the typep function is a set membership test,
while subtypep is a subset test.
[Function]
typep object
type
typep is a predicate that is true if object is
of type type, and is false otherwise. Note that an object can
be ``of’’ more than one type, since one type can include another. The
type may be any of the type specifiers mentioned in chapter 4 except that it may not be or
contain a type specifier list whose first element is
function or values. A specifier of the form
(satisfiesfn) is handled
simply by applying the function fn to object (see
funcall); the object is considered to be of the
specified type if the result is not nil.

X3J13 voted in January 1989 (ARRAY-TYPE-ELEMENT-TYPE-SEMANTICS) to
change typep to give specialized array and
complex type specifiers the same meaning for purposes of
type discrimination as they have for declaration purposes. Of course,
this also applies to such type specifiers as vector and
simple-array (see section 4.5). Thus
(typep foo '(array bignum))
in the first edition asked the question, Is foo an array
specialized to hold bignums? but under the new interpretation asks the
question, Could the array foo have resulted from giving
bignum as the :element-type argument to
make-array?

[Function]
subtypep type1
type2
The arguments must be type specifiers that are acceptable to
typep. The two type specifiers are compared; this predicate
is true if type1 is definitely a (not necessarily proper)
subtype of type2. If the result is nil, however,
then type1 may or may not be a subtype of type2
(sometimes it is impossible to tell, especially when
satisfies type specifiers are involved). A second returned
value indicates the certainty of the result; if it is true, then the
first value is an accurate indication of the subtype relationship. Thus
there are three possible result combinations:
t t type1 is definitely a subtype of type2
nil t type1 is definitely not a subtype of type2
nil nil subtypep could not determine the relationship

X3J13 voted in January 1989 (SUBTYPEP-TOO-VAGUE) to place certain
requirements upon the implementation of subtypep, for it
noted that implementations in many cases simply ``give up’’ and return
the two values nil and nil when in fact it
would have been possible to determine the relationship between the given
types. The requirements are as follows, where it is understood that a
type specifier s involves a type specifier u
if either s contains an occurrence of u directly or
s contains a type specifier w defined by
deftype whose expansion involves u.
subtypep is not permitted to return a second value of
nil unless one or both of its arguments involves
satisfies, and, or,
not, or member.subtypep should signal an error when one or both of its
arguments involves values or the list form of the
function type specifier.subtypep must always return the two values
t and t in the case where its arguments, after
expansion of specifiers defined by deftype, are
equal.In addition, X3J13 voted to clarify that in some cases the
relationships between types as reflected by subtypep may be
implementation-specific. For example, in an implementation supporting
only one type of floating-point number,
(subtypep 'float 'long-float) would return t
and t, since the two types would be identical.
Note that satisfies is an exception because
relationships between types involving satisfies are
undecidable in general, but (as X3J13 noted) and,
or, not, and member are merely
very messy to deal with. In all likelihood these will not be addressed
unless and until someone is willing to write a careful specification
that covers all the cases for the processing of these type specifiers by
subtypep. The requirements stated above were easy to state
and probably suffice for most cases of interest.
X3J13 voted in January 1989 (ARRAY-TYPE-ELEMENT-TYPE-SEMANTICS) to
change subtypep to give specialized array and
complex type specifiers the same meaning for purposes of
type discrimination as they have for declaration purposes. Of course,
this also applies to such type specifiers as vector and
simple-array (see section 4.5).
If A and B are type specifiers (other than
*, which technically is not a type specifier anyway), then
(arrayA) and
(arrayB) represent the
same type in a given implementation if and only if they denote arrays of
the same specialized representation in that implementation; otherwise
they are disjoint. To put it another way, they represent the same type
if and only if
(upgraded-array-element-type 'A)
and
(upgraded-array-element-type 'B)
are the same type. Therefore
(subtypep '(array A) '(array B))
is true if and only if
(upgraded-array-element-type 'A)
is the same type as
(upgraded-array-element-type 'B).
The complex type specifier is treated in a similar but
subtly different manner. If A and B are two type
specifiers (but not *, which technically is not a type
specifier anyway), then
(complexA) and
(complexB) represent the
same type in a given implementation if and only if they refer to complex
numbers of the same specialized representation in that implementation;
otherwise they are disjoint. Note, however, that there is no function
called make-complex that allows one to specify a particular
element type (then to be upgraded); instead, one must describe
specialized complex numbers in terms of the actual types of the parts
from which they were constructed. There is no number of type (or rather,
representation) float as such; there are only
numbers of type single-float, numbers of type
double-float, and so on. Therefore we want
(complex single-float) to be a subtype of
(complex float).
The rule, then, is that
(complexA) and
(complexB) represent the
same type (and otherwise are disjoint) in a given implementation if and
only if either the type A is a subtype of B,
or
(upgraded-complex-part-type 'A)
and
(upgraded-complex-part-type 'B)
are the same type. In the latter case
(complexA) and
(complexB) in fact refer
to the same specialized representation. Therefore
(subtypep '(complex A) '(complex B))
is true if and only if the results of
(upgraded-complex-part-type 'A)
and
(upgraded-complex-part-type 'B)
are the same type.
Under this interpretation
(subtypep '(complex single-float) '(complex float))
must be true in all implementations; but
(subtypep '(array single-float) '(array float))
is true only in implementations that do not have a specialized array
representation for single-float elements distinct from that
for float elements in general.

![]()
Next: Specific Data Type
Up: Data Type Predicates
Previous: Data Type
Predicates
AI.Repository@cs.cmu.edu