Function SUBTYPEP
subtypep type-1 type-2 &optional environment => subtype-p, valid-p
type-1 - 型指定子
type-2 - 型指定子
environment - 環境オブジェクト。デフォルトはnilであり、 これはnullのレキシカルな環境と現在のグローバルな環境を示します。
subtype-p - generalized-boolean
valid-p - generalized-boolean
もしtype-1がtype-2の認識可能なサブタイプであれば最初の値はtrueです。 そうではないときは最初の値はfalseであり、 これはtype-1がtype-2のサブタイプではないか、 あるいはtype-1がtype-2がサブタイプではあるが 認識可能なサブタイプではないことを意味します。
第二返却値は、最初の値が確実であるかを示します。 もしこの値がtrueなら、 最初の値はサブタイプの関係が正確であることを示します (最初の値がtrueであれば第二返却値は常にtrueです)。
次の表は、可能性のある返却値の組み合わせを要約したものです。
| Value 1 | Value 2 | 意味 |
|---|---|---|
| true | true | type-1は確実にtype-2のサブタイプ |
| false | true | type-2は確実にtype-2のサブタイプではない |
| false | false | subtypepはこの関係を決定できないので、type-1はtype-2のサブタイプかもしれないしそうではないかもしれない |
Figure 4-9. subtypepの返却値の可能性
subtypepは、 次に示す型指定子のうち、少なくとものひとつを引数に含んでいたときのみ 多値であるfalse、falseを返却します。 その型指定子は、 and, eql, リストフォームのfunction, member, not, or, satisfies, valuesです (型指定子は、型展開後にそれらのシンボルが含まれる位置で 型指定子が意味のある使われ方をして呼び出されているときは、 そのようなシンボルを含むことになります)。 このような結果のひとつとして もしtype-1もtype-2もそれらの型指定子を含まないときは、 subtypepは正確な関係を決定する義務があります。 とくにsubtypepは もしそれらの引数がequalで一致しており それらの型指定子を含まないときは、 多値のtrue、trueを返却します。
もしtype-1とtype-2の両方が figure_4-2で表される名前のみ含まれているときか、 または型の名前がdefstructか define-conditionか defclassか これらの名前の展開による派生型であるときは、 subtypepは決して第二返却値がnilになりません。 figure_4-2のリスト内の型指定子や defclassとdefstructによる名前は、 派生された型として実装される場合もありますが、 subtypepはそれらの型を原始的なものとみなします。
subtypepによって反映される型と型との関係は、 特定の実装によって指定されます。 例えば、もし実装が浮動小数の型を singleただひとつサポートしていた場合、 その実装は(subtypep 'float 'long-float)を true, trueで返却します(2つの型が同一の場合)。
*以外の全てをT1とT2としたとき、 (array T1)と(array T2)は違う型指定子ですが、 もしそれらを参照する配列が正確に同じspecializedの表現のときは、 常に同じものの集合を参照します。 例えば、もし (upgraded-array-element-type 'T1)と (upgraded-array-element-type 'T2)が 常に同じオブジェクトの集合を参照する 違う型指定子を返却するようなときです。 別の言い方をすると、
`(array type-specifier)と
`(array ,(upgraded-array-element-type 'type-specifier))はどちらも同じspecialized配列で表現された 集合を参照しています。 *以外の全てのT1とT2において、 (array T1)と(array T2)が それぞれ区別できるspecializedな表現により違った配列を参照しているときは、 2つの型の共通部分は空の集合です。
つまり、
(subtypep '(array T1) '(array T2)) => trueであるというのは、
(upgraded-array-element-type 'T1)
(upgraded-array-element-type 'T2) 上記の返却値は、 常に同じオブジェクトの集合を参照しているような 違った2つの型指定子が返却されます。
*以外の全てをT1とT2としたとき、
(subtypep '(complex T1) '(complex T2)) => true, trueという結果が得られるのは、下記の2つのどちらかの条件のときです。
T1はT2のサブタイプであるか、
(upgraded-array-element-type 'T1)と (upgraded-array-element-type 'T2)が 常に同じオブジェクトの集合を参照する 違う型指定子を返却するようなときです。 このような場合、(complex T1)と(complex T2)の両方は、 どちらも同じspecializedな表現を参照します。
それ以外のときは、false, falseを返却します。
下記のフォームについて、
(subtypep '(complex single-float) '(complex float))これはすべtの実装においてtrueを返却しなければなりません。 しかし下記のフォーム
(subtypep '(array single-float) '(array float))こちらについては、 配列のspecializedな表現でsingle-floatと他の浮動小数を 区別できない処理系でのみtrueが返却されます。
(subtypep 'compiled-function 'function) => true, true
(subtypep 'null 'list) => true, true
(subtypep 'null 'symbol) => true, true
(subtypep 'integer 'string) => false, true
(subtypep '(satisfies dummy) nil) => false, implementation-dependent
(subtypep '(integer 1 3) '(integer 1 4)) => true, true
(subtypep '(integer (0) (0)) 'nil) => true, true
(subtypep 'nil '(integer (0) (0))) => true, true
(subtypep '(integer (0) (0)) '(member)) => true, true ;or false, false
(subtypep '(member) 'nil) => true, true ;or false, false
(subtypep 'nil '(member)) => true, true ;or false, false<aet-x>と<aet-y>は その実装において常に同じオブジェクトの集合を参照していない 2つの違った型指定子であるとします。 しかしmake-array関数は、 同じ配列の型としてオブジェクトを返却します。
したがって、次のようになります。
(subtypep (array-element-type (make-array 0 :element-type '<aet-x>))
(array-element-type (make-array 0 :element-type '<aet-y>)))
=> true, true
(subtypep (array-element-type (make-array 0 :element-type '<aet-y>))
(array-element-type (make-array 0 :element-type '<aet-x>)))
=> true, trueもし(array <aet-x>)と(array <aet-y>)が 正確に同じオブジェクトの集合のための違う名前であるとき、 それらの名前は常に同じオブジェクトの集合を参照しなければなりません。 これの意味することは、次のテストの集合もまたtrueということです。
(subtypep '(array <aet-x>) '(array <aet-y>)) => true, true
(subtypep '(array <aet-y>) '(array <aet-x>)) => true, trueなし。
なし。
なし。
subtypepの仕様の arrayとcomplexの型の間にある 小さな違いは重要です。 なぜなら、実際の部分の型と独立して 返却値の部分の型を指定できるような 複素数を作成する関数が存在しないからです。 したがって、複素数の型の場合は、 実際の部分の型はひとつ以上の型はあるものの、 その数を参照して決定されます。 例えば、17は(mod 18)の型ですし、 同様に(mod 256)の型であり、integerの型です。 そして、2.3f5はsingle-floatの型であり、 floatの型でもあります。