User Tools


Differences

This shows you the differences between two versions of the page.

Link to this comparison view

cl:functions:subtypep [2019/09/14 05:00]
cl:functions:subtypep [2019/09/22 06:00] (current)
Line 1: Line 1:
 +====== 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}