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
の型でもあります。