User Tools


====== Function SUBTYPEP ====== ====Syntax==== * **subtypep** //type-1// //type-2// ''&optional'' //environment// → //subtype-p//, //valid-p// ====Arguments and Values==== * //type-1// - a //[[CL:Glossary:type specifier]]//. * //type-2// - a //[[CL:Glossary:type specifier]]//. * //environment// - an //[[CL:Glossary:environment]]// //[[CL:Glossary:object]]//. The default is **[[CL:Constant Variables:nil]]**, denoting the //[[CL:Glossary:null lexical environment]]// and the current //[[CL:Glossary:global environment]]//. * //subtype-p// - a //[[CL:Glossary:generalized boolean]]//. * //valid-p// - a //[[CL:Glossary:generalized boolean]]//. ====Description==== If //type-1// is a //[[CL:Glossary:recognizable subtype]]// of //type-2//, the first //[[CL:Glossary:value]]// is //[[CL:Glossary:true]]//. Otherwise, the first //[[CL:Glossary:value]]// is //[[CL:Glossary:false]]//, indicating that either //type-1// is not a //[[CL:Glossary:subtype]]// of //type-2//, or else //type-1// is a //[[CL:Glossary:subtype]]// of //type-2// but is not a //[[CL:Glossary:recognizable subtype]]//. A second //[[CL:Glossary:value]]// is also returned indicating the `certainty' of the first //[[CL:Glossary:value]]//. If this value is //[[CL:Glossary:true]]//, then the first value is an accurate indication of the //[[CL:Glossary:subtype]]// relationship. (The second //[[CL:Glossary:value]]// is always //[[CL:Glossary:true]]// when the first //[[CL:Glossary:value]]// is //[[CL:Glossary:true]]//.) The table below summarizes the possible combinations of //[[CL:Glossary:values]]// that might result. ^ Value 1 ^ Value 2 ^ Meaning ^ | //[[CL:Glossary:true]]// | //[[CL:Glossary:true]]// | //type-1// is definitely a //[[CL:Glossary:subtype]]// of //type-2//. | | //[[CL:Glossary:false]]// | //[[CL:Glossary:true]]// | //type-1// is definitely not a //[[CL:Glossary:subtype]]// of //type-2//. | | //[[CL:Glossary:false]]// | //[[CL:Glossary:false]]// | **subtypep** could not determine the \\ relationship, so //type-1// might or might \\ not be a //[[CL:Glossary:subtype]]// of //type-2//.| **subtypep** is permitted to return the //[[CL:Glossary:values]]// //[[CL:Glossary:false]]// and //[[CL:Glossary:false]]// only when at least one argument involves one of these //[[CL:Glossary:type specifiers]]//: **[[CL:Declarations:and]]**, **[[CL:Declarations:eql]]**, the list form of **[[CL:Declarations:function]]**, **[[CL:Declarations:member]]**, **[[CL:Declarations:not]]**, **[[CL:Declarations:or]]**, **[[CL:Declarations:satisfies]]**, or **[[CL:Declarations:values]]**. (A //[[CL:Glossary:type specifier]]// "involves" such a //[[CL:Glossary:symbol]]// if, after being //[[CL:Glossary:type expanded]]//, it contains that //[[CL:Glossary:symbol]]// in a position that would call for its meaning as a //[[CL:Glossary:type specifier]]// to be used.) One consequence of this is that if neither //type-1// nor //type-2// involves any of these //[[CL:Glossary:type specifiers]]//, then **subtypep** is obliged to determine the relationship accurately. In particular, **subtypep** returns the //[[CL:Glossary:values]]// //[[CL:Glossary:true]]// and //[[CL:Glossary:true]]// if the arguments are **[[CL:Functions:equal]]** and do not involve any of these //[[CL:Glossary:type specifiers]]//. **subtypep** never returns a second value of **[[CL:Constant Variables:nil]]** when both //type-1// and //type-2// involve only the names in \figref\StandardizedAtomicTypeSpecs, or names of //[[CL:Glossary:types]]// defined by **[[CL:Macros:defstruct]]**, **[[CL:Macros:define-condition]]**, or **[[CL:Macros:defclass]]**, or //[[CL:Glossary:derived types]]// that expand into only those names. While //[[CL:Glossary:type specifiers]]// listed in \figref\StandardizedAtomicTypeSpecs\ and names of **[[CL:Macros:defclass]]** and **[[CL:Macros:defstruct]]** can in some cases be implemented as //[[CL:Glossary:derived types]]//, **subtypep** regards them as primitive. The relationships between //[[CL:Glossary:types]]// reflected by **subtypep** are those specific to the particular implementation. For example, if an implementation supports only a single type of floating-point numbers, in that implementation ''(subtypep 'float 'long-float)'' returns the //[[CL:Glossary:values]]// //[[CL:Glossary:true]]// and //[[CL:Glossary:true]]// (since the two //[[CL:Glossary:types]]// are identical). For all //T1// and //T2// other than ''*'', ''([[CL:Types:array]] //T1//)'' and ''([[CL:Types:array]] //T2//)'' are two different //[[CL:Glossary:type specifiers]]// that always refer to the same sets of things if and only if they refer to //[[CL:Glossary:array|arrays]]// of exactly the same specialized representation, i.e. if ''([[CL:Functions:upgraded-array-element-type]] '//T1//)'' and ''([[CL:Functions:upgraded-array-element-type]] '//T2//)'' return two different //[[CL:Glossary:type specifiers]]// that always refer to the same sets of //[[CL:Glossary:object|objects]]//. This is another way of saying that ''`([[CL:Types:array]] //type-specifier//)'' and ''`([[CL:Types:array]] ,([[CL:Functions:upgraded-array-element-type]] '//type-specifier//))'' refer to the same set of specialized //[[CL:Glossary:array]]// representations. For all //T1// and //T2// other than ''*'', the intersection of ''([[CL:Types:array]] //T1//)'' and ''([[CL:Types:array]] //T2//)'' is the empty set if and only if they refer to //[[CL:Glossary:array|arrays]]// of different, distinct specialized representations. Therefore: <blockquote> (subtypep '([[CL:Types:array]] T1) '([[CL:Types:array]] T2)) <r>//[[CL:Glossary:true]]// </r> </blockquote> if and only if ''([[CL:Functions:upgraded-array-element-type]] 'T1) and ([[CL:Functions:upgraded-array-element-type]] 'T2)'' return two different //[[CL:Glossary:type specifiers]]// that always refer to the same sets of //[[CL:Glossary:object|objects]]//. For all type-specifiers //T1// and //T2// other than ''*'', if: * 1. ''T1'' is a //[[CL:Glossary:subtype]]// of ''T2'', or * 2. ''(upgraded-complex-part-type '//T1//)'' and ''(upgraded-complex-part-type '//T2//)'' return two different //[[CL:Glossary:type specifiers]]// that always refer to the same sets of //[[CL:Glossary:object|objects]]//; in this case, ''(complex //T1//)'' and ''(complex //T2//)'' both refer to the same specialized representation, then the following is true: <blockquote> (subtypep '([[CL:Types:complex]] //T1//) '([[CL:Types:complex]] //T2//)) <r>//[[CL:Glossary:true]]// //[[CL:Glossary:true]]//</r> </blockquote> The //[[CL:Glossary:values]]// are //[[CL:Glossary:false]]// and //[[CL:Glossary:true]]// otherwise. ------ The form ''(subtypep '([[CL:Types:complex]] single-float) '([[CL:Types:complex]] float))'' must return //[[CL:Glossary:true]]// in all implementations, but ''(subtypep '([[CL:Functions:array]] [[CL:Types:single-float]]) '([[CL:Functions:array]] [[CL:Types:float]]))'' returns //[[CL:Glossary:true]]// only in implementations that do not have a specialized //[[CL:Glossary:array]]// representation for //[[CL:Glossary:single floats]]// distinct from that for other //[[CL:Glossary:floats]]//. ====Examples==== <blockquote> (subtypep '[[CL:Types:compiled-function]] '[[CL:Types:function]]) <r>//[[CL:Glossary:true]]// //[[CL:Glossary:true]]// </r> (subtypep '[[CL:Types:null]] '[[CL:Types:list]]) <r>//[[CL:Glossary:true]]// //[[CL:Glossary:true]]// </r> (subtypep '[[CL:Types:null]] '[[CL:Types:symbol]]) <r>//[[CL:Glossary:true]]// //[[CL:Glossary:true]]// </r> (subtypep '[[CL:Types:integer]] '[[CL:Types:string]]) <r>//[[CL:Glossary:false]]// //[[CL:Glossary:true]]// </r> (subtypep '([[CL:Types:satisfies]] dummy) [[CL:Types:nil]]) <r>//[[CL:Glossary:false]]// //[[CL:Glossary:implementation-dependent]]// </r> (subtypep '([[CL:Types:integer]] 1 3) '([[CL:Types:integer]] 1 4)) <r>//[[CL:Glossary:true]]// //[[CL:Glossary:true]]// </r> (subtypep '(integer (0) (0)) '[[CL:Types:nil]]) <r>//[[CL:Glossary:true]]// //[[CL:Glossary:true]]// </r> (subtypep '[[CL:Types:nil]] '([[CL:Types:integer]] (0) (0))) <r>//[[CL:Glossary:true]]// //[[CL:Glossary:true]]// </r> (subtypep '([[CL:Types:integer]] (0) (0)) '([[CL:Types:member]])) <r>//[[CL:Glossary:true]]// //[[CL:Glossary:true]]// </r> <r>//or// //[[CL:Glossary:false]]// //[[CL:Glossary:false]]// </r> (subtypep '([[CL:Types:member]]) '[[CL:Types:nil]]) <r>//[[CL:Glossary:true]]// //[[CL:Glossary:true]]//</r> <r>//or// //[[CL:Glossary:false]]// //[[CL:Glossary:false]]// </r> (subtypep '[[CL:Types:nil]] '([[CL:Types:member]])) <r>//[[CL:Glossary:true]]// //[[CL:Glossary:true]]// </r> <r>//or// //[[CL:Glossary:false]]// //[[CL:Glossary:false]]// </r> </blockquote> Let ''<aet-x>'' and ''<aet-y>'' be two distinct //[[CL:Glossary:type specifiers]]// that do not always refer to the same sets of //[[CL:Glossary:object|objects]]// in a given implementation, but for which **[[CL:Functions:make-array]]**, will return an //[[CL:Glossary:object]]// of the same //[[CL:Glossary:array]]// //[[CL:Glossary:type]]//. Thus, in each case: <blockquote> (subtypep ([[CL:Functions:array-element-type]] ([[CL:Functions:make-array]] 0 :element-type '//<aet-x>//)) ([[CL:Functions:array-element-type]] ([[CL:Functions:make-array]] 0 :element-type '//<aet-y>//))) <r>//[[CL:Glossary:true]]// //[[CL:Glossary:true]]//</r> (subtypep ([[CL:Functions:array-element-type]] ([[CL:Functions:make-array]] 0 :element-type '//<aet-y>//)) ([[CL:Functions:array-element-type]] ([[CL:Functions:make-array]] 0 :element-type '//<aet-x>//))) <r>//[[CL:Glossary:true]]// //[[CL:Glossary:true]]//</r> </blockquote> If ''(array <aet-x>)'' and ''(array <aet-y>)'' are different names for exactly the same set of //[[CL:Glossary:object|objects]]//, these names should always refer to the same sets of //[[CL:Glossary:object|objects]]//. That implies that the following set of tests are also true: <blockquote> (subtypep '([[CL:Types:array]] <aet-x>) '([[CL:Types:array]] <aet-y>)) <r>//[[CL:Glossary:true]]// //[[CL:Glossary:true]]// </r> (subtypep '([[CL:Types:array]] <aet-y>) '([[CL:Types:array]] <aet-x>)) <r>//[[CL:Glossary:true]]// //[[CL:Glossary:true]]// </r> </blockquote> ====Side Effects==== None. ====Affected By==== None. ====Exceptional Situations==== None. ====See Also==== * {\secref\Types} ====Notes==== The small differences between the **subtypep** specification for the **[[CL:Types:array]]** and **[[CL:Types:complex]]** types are necessary because there is no creation function for //[[CL:Glossary:complexes]]// which allows the specification of the resultant part type independently of the actual types of the parts. Thus in the case of the type **[[CL:Types:complex]]**, the actual type of the parts is referred to, although a //[[CL:Glossary:number]]// can be a member of more than one //[[CL:Glossary:type]]//. For example, ''17'' is of //[[CL:Glossary:type]]// ''([[CL:Types:mod]] 18)'' as well as //[[CL:Glossary:type]]// ''([[CL:Types:mod]] 256)'' and //[[CL:Glossary:type]]// **[[CL:Types:integer]]**; and ''2.3f5'' is of type **[[CL:Types:single-float]]** as well as //[[CL:Glossary:type]]// **[[CL:Types:float]]**. \issue{ARRAY-TYPE-ELEMENT-TYPE-SEMANTICS:UNIFY-UPGRADING} \issue{SUBTYPEP-ENVIRONMENT:ADD-ARG} \issue{SUBTYPEP-TOO-VAGUE:CLARIFY-MORE} \issue{ARRAY-TYPE-ELEMENT-TYPE-SEMANTICS:UNIFY-UPGRADING} \issue{ARRAY-TYPE-ELEMENT-TYPE-SEMANTICS:UNIFY-UPGRADING}