概念的には2種類のコンディションオブジェクトがある。シンプルコンディションと合成コンディションである。オブジェクトがシンプルコンディションか合成コンディションのどちらかであれば単純にコンディションである。 合成コンディションはR6RS:翻訳:R6RS:11.1 Base typesで説明されている基本型とは互いに排他的な型を形成する。シンプルコンディションは例外状況の1つの状態を記述する。合成コンディションは例外状況の複数の状態をシンプルコンディションのリストとして、構成要素として保持する。このセクションで説明されている動作の大部分はシンプルコンディションを1つの構成要素しか持たない合成コンディションと同一に扱っている。 &condition のサブタイプ t に対して、型 t のコンディションは型 t の構造体か型 t を保持する合成コンディションのどちらかである。
シンプルコンディションは &condition レコード型のサブタイプの構造体である。 &condition 型はフィールドを持たず、封印されてもおらず不透明でもない。
condition 手続きは同じ順序のコンディション列を持ったコンディションオブジェクトを返す。 すなわち condition1 の構成要素が condition1 にあるときと同じ順序で一番先頭に現れ condition2 の構成要素が続く。構成要素の個数の合計が 0 か、1より大きければ変えされるコンディションは合成コンディションである。それ以外の場合はシンプルコンディションである。
simple-conditions 手続きはコンディションの構成要素のリストを返す。そのリストはコンディション作成時と同じ順序である。戻り値のリストは変更不能である。戻り値のリストが修正された場合、元のコンディションへの効果は規定されていない。
注:コンディションはその引数をシンプルコンディションに分解するので simple-conditions は常にシンプルコンディションの「平坦にした」リストを返す。
obj がシンプルコンディションから合成コンディションの時に #t を返しそれ以外は #f を返す。
rtd は &condition のサブタイプの構造体記述子でなければならない。 condition-predicate 手続きは 1 引数の手続きを返す。この手続きは引数が rtd のコンディション型のコンディションのときに #t を返す。すなわちその構造体(かそのサブタイプ)のシンプルコンディションかもしくはそのようなシンプルコンディションを構成要素に持つ合成コンディションの場合に #t それ以外は #f である。
rtd は &condition のサブタイプの構造体記述子でなければならない。 condition-accessor 手続きは 1 引数の手続きを返す。引数は rtd によって表現されるコンディション型でなければならない。この手続きは rtd によって表現される型の構造体の1つめの構成要素を取り出しその構成要素を proc に適用した結果を返す。
(ひげぽんによる注) condition-accessor の返す手続きを accessor-proc とする。(accessor-proc c) と呼び出した場合、c は合成コンディションの可能性もある。 その場合 c から rtd に相当するコンディションを探し出し最初に見つかった rtd に対して (proc rtd-found) とする。 という意味で「This procedure extracts the first component of the condition of the type represented by rtd, and returns the result of applying proc to that component. 」と書かれているのだと思う。
(define-record-type (&cond1 make-cond1 real-cond1?) (parent &condition) (fields (immutable x real-cond1-x))) (define cond1? (condition-predicate (record-type-descriptor &cond1))) (define cond1-x (condition-accessor (record-type-descriptor &cond1) real-cond1-x)) (define foo (make-cond1 'foo)) (condition? foo) => #t (cond1? foo) => #t (cond1-x foo) => foo (define-record-type (&cond2 make-cond2 real-cond2?) (parent &condition) (fields (immutable y real-cond2-y))) (define cond2? (condition-predicate (record-type-descriptor &cond2))) (define cond2-y (condition-accessor (record-type-descriptor &cond2) real-cond2-y)) (define bar (make-cond2 'bar)) (condition? (condition foo bar)) => #t (cond1? (condition foo bar)) => #t (cond2? (condition foo bar)) => #t (cond1? (condition foo)) => #t (real-cond1? (condition foo)) => unspecified (real-cond1? (condition foo bar)) => #f (cond1-x (condition foo bar)) => foo (cond2-y (condition foo bar)) => bar (equal? (simple-conditions (condition foo bar)) (list foo bar)) => #t (equal? (simple-conditions (condition foo (condition bar))) (list foo bar)) => #t
構文: <condition-type>、 <supertypes>、 <constructor>、 <predicate> は全て識別子でなければならない。それぞれの <field-spec> は以下のフォームでなければならない
(<field> <accessor>)
ここで、 <field> と <accessor> は識別子でなければならない。
意味論: define-condition-type フォームは <condition-type> (R6RS:翻訳:R6RS:6.2 Procedure entries を見よ)構造体型の定義へと展開される。その構造体は不透明でなく凍結もされておらずそのフィールドは不変である。 <supertype> はその親の型をもつ。残りの識別子は以下のように束縛される:
(define-condition-type &c &condition make-c c? (x c-x)) (define-condition-type &c1 &c make-c1 c1? (a c1-a)) (define-condition-type &c2 &c make-c2 c2? (b c2-b)) (define v1 (make-c1 "V1" "a1")) (c? v1) => #t (c1? v1) => #t (c2? v1) => #f (c-x v1) => "V1" (c1-a v1) => "a1" (define v2 (make-c2 "V2" "b2")) (c? v2) => #t (c1? v2) => #f (c2? v2) => #t (c-x v2) => "V2" (c2-b v2) => "b2" (define v3 (condition (make-c1 "V3/1" "a3") (make-c2 "V3/2" "b3"))) (c? v3) => #t (c1? v3) => #t (c2? v3) => #t (c-x v3) => "V3/1" (c1-a v3) => "a3" (c2-b v3) => "b3" (define v4 (condition v1 v2)) (c? v4) => #t (c1? v4) => #t (c2? v4) => #t (c-x v4) => "V1" (c1-a v4) => "a1" (c2-b v4) => "b2" (define v5 (condition v2 v3)) (c? v5) => #t (c1? v5) => #t (c2? v5) => #t (c-x v5) => "V2" (c1-a v5) => "a3" (c2-b v5) => "b2"