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
(satisfies
fn
)
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
(array
A
)
and
(array
B
)
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
(complex
A
)
and
(complex
B
)
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
(complex
A
)
and
(complex
B
)
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
(complex
A
)
and
(complex
B
)
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