[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Gaucheの例外システムは次の3つのコンポーネントから構成されています。 (1)例外状況が発生したことを通知する方法、 (2)例外状況をどのように処理するかを指定する方法、 (3)例外状況を知らせたコードとそれを処理するコードがやりとりするための 標準オブジェクト(コンディション)。
普通これらの3つのコンポーネントは一緒に使われます。 そこで、最初に例を用いて典型的な使い方について説明し、 そのあとでそれぞれの機能について詳しく解説します。
用語について: いくつかの言語では例外(exception)というと、 例外的状況に遭遇したコードとそのハンドラがやりとりをするために用られる オブジェクトのことを指します。Gaucheではそのようなオブジェクトのことを言うときには、 SRFI-35にならってコンディション(condition)を使います。 例外というのは、状況であり、コンディションはそれを記述する 実行時のオブジェクトです。
6.17.1 例外処理の概要 | ||
6.17.2 例外の通知 | ||
6.17.3 例外の処理 | ||
6.17.4 コンディション |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
最もよくある例外処理のひとつは、組み込みあるいは
ライブラリの手続きから発生した特定のエラーを捕捉するというものです。
guard
マクロがこのような目的の場合に使えます。
コードは以下のような感じになるでしょう。
(guard (exc ((condition-has-type? exc <read-error>) (format #t "read error!") 'read-error) (else 'other-error)) (read-from-string "(abc")) |
guard
節の cadr 部は (variable clause …)
という
形式です。この例では、変数は exc
で、2つの節があります。
それぞれの clause は cond
と似た形式になります。
guard
の cddr 部は本体で、式のリストです。この例では、式は
(read-from-string "(abc")
のひとつだけです。
guard
はその本体部を実行するところから始めます。
read-from-string
は構文エラーに出くわすと、<read-error>
型の
エラーを発生させます。guard
フォームがこのエラーを捕捉し、
そのコンディションオブジェクトを変数excに束縛し、excの後の
節を、cond
と同じようにチェックします。この場合、投げられた
コンディションは <read-error>
なので、最初の節のテストを満し、
その節の残りの部分が実行されます。すなわち、"read error!"
が
印字され、シンボル read-error
が返ります。
他の言語を使い慣れていれば、同じパターンであることがわかると思います。
guard
フォームの cddr 部は、C++やJavaの try 節、あるいは、
Common Lisp の handler-case
の cadr 部に似ています。
また、guard
フォームの cdadr 部は、catch
節あるいは、
handler-case
の cddr 部に似ています。
テスト式においては、投げられたコンディションのタイプをチェックする
のが普通です。condition-has-type?
という関数が
SRFI-35 で定義されていますが、これはちょっと冗長です。Gauche の
コンディションクラスは述語のようも使えるようになっており、上の
式は以下のように書くこともができます。
(guard (exc ((<read-error> exc) 'read-error) (else 'other-error)) (read-from-string "(abc"))) |
注意事項: 一般的には、投げられたコンディションが特定の
タイプであるかをチェックするのにis-a?
は使えません。
コンディションが合成されたものである可能性があるからです。
合成されたコンディションについての
詳細は コンディション を参照してください。
もし、clause のどのテストも満されず、かつ else
節があたえられて
いなければ、その例外は guard
から「抜け」ます。すなわち、guard
の外側のレベルあるいはトップレベルで処理されることになります。たとえば、
以下の guard
フォームでは、<read-error>
と
<system-error>
としか処理できず、もし、本体が他のタイプのコンディション
を投げてきたら、その外側のレベルで処理しなければなりません。
(guard (exc ((<read-error> exc) (handle-read-error)) ((<system-error> exc) (handle-system-error)) ) body …) |
guard
および他の低レベルの例外処理の構成についての詳細は
例外の処理 を参照してください。
例外を通知する一般的な方法は raise
手続きを使うことです。
(raise condition) |
conditionにはどんなオブジェクトでも渡すことができます。
それをどのように解釈するかはひとえに例外ハンドラにかかってます。
もし、コンディションとして整数があがってくるというのが判っていれば、
guard
で以下のように捕捉することができます。
(guard (exc ((integer? exc) 'raised)) (raise 3)) |
とはいうものの、<condition>
あるいはそのサブクラスのインスタンスを
使うのが好ましいというのが通例です。condition
マクロはコンディション
オブジェクトを作成するのに使えます。以下の例は、いくつかのスロット値をもち
それらを発生させるコンディションの作りかたを示したものです。
;; create and raise an error condition (raise (condition (<error> (message "An error occurred.")))) ;; create and raise a system error condition (raise (condition (<system-error> (message "A system error occurred.") (errno EINTR)))) |
condition
マクロおよび、どのようなコンディションクラスが用意
されているかの詳細については コンディション を参照してください。
最も一般的なコンディションのタイプはエラーコンディションなので、
error
および errorf
という便利な手続きが
用意されています。これらはメッセージ付きのエラーコンディションを
生成し、それを発生させます。
;; `error' concatenates the arguments into a message. (unless (integer? obj) (error "Integer expected, but got:" obj)) ;; `errorf' uses format to create a message. (unless (equal? x y) (errorf "~s and ~s don't match" x y)) |
注意事項: いくつかの言語での例外を投げる機構、たとえば、
Cl++やJavaの throw
はその継続を破棄します。これとは違い
Schemeの raise
はその呼び出し元へ戻ることができます。もし、
raise
で元へもどらないで欲しいのなら、簡便な方法としては、
常にエラーコンディションの一つをわたるようにするというのがあります。
そうすると Gauche では raise
は戻らないことを保証します。
raise
の詳細については、例外の通知を参照してください。
独自のコンディションクラスを定義することが可能で、そうすることで、 アプリケーション固有の情報を例外が発生した点からハンドラへ渡すことが できます。
Gauche のフレームワーク(SRFI-35)に適合させるためには、新しく定義する
コンディションクラスは組み込みの <condition>
クラスあるいは
その子孫を継承し、また、メタクラス <condition-meta>
のインスタンスであることが望まれます。
可搬性を増すと同時に上の慣例を確実にするための方法のひとつは、
define-condition-type
マクロを使うことです。これは、
SRFI-35
で定義されています。
(define-condition-type <myapp-error> <error> myapp-error? (debug-info myapp-error-debug-info) (reason myapp-error-reason)) |
これは、(Gauche内のクラス)<myapp-err>
を定義するもので、
このクラスにはmyapp-error?
という述語とアクセサのあるスロット
があります。こうすれば、以下のようなコードで新しいコンディション
型が使えます。
(guard (exc ((myapp-error? exc) (let ((debug-info (myapp-error-debug-info exc)) (reason (myapp-error-reason exc))) ... handle myapp-error ...))) ... ... (if (something-went-wrong) (raise (condition (<myapp-error> (debug-info "during processing xxx") (reason "something went wrong"))))) ... ... ) |
SRFIとの互換性が重要でないなら、Gaucheの拡張されたerror
手続きを
使うと<error>
のサブタイプであるコンディションを投げるコードを
より簡潔に書くことができます。
(if (something-went-wrong) (error <myapp-error> :debug-info "during processing xxx" :reason "something went wrong")) |
Gauche のオブジェクトシステムでコンディション型がどのように実装されているかは
define-condition-type
マクロの解説を参照してください。
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
最も良くある例外ケースはエラーです。単純なエラーを通知するために、
ふたつの簡単な関数が用意されています。
複合コンディションを通知する必要がある場合は
下で説明するraise
手続きを使って下さい。
[SRFI-23+] エラーを通知します。最初の形式は、
stringとarg …からなるメッセージを持つ
<error>
コンディションを作成それをraise
します。
この形式はsrfi-23のerror
と互換です。
gosh> (define (check-integer x) (unless (integer? x) (error "Integer required, but got:" x))) check-integer gosh> (check-integer "a") *** ERROR: Integer required, but got: "a" Stack Trace: _______________________________________ |
2番目の形式は<error>
以外のエラーコンディションを通知したいときに
使います。condition-typeはコンディションタイプ
でなければなりません (コンディションタイプについてはコンディションを
参照して下さい)。その後に、キーワードと値のリストを与えることで
コンディションのスロットを初期化することができます。また、その後に
メッセージを構成する文字列と他のオブジェクトのリストを与えることができます。
(define-condition-type <my-error> <error> #f (reason) (priority)) ... (unless (memq operation *supported-operations*) (error <my-error> :reason 'not-supported :priority 'urgent "Operation not supported:" operation)) ... |
error
に似ていますが、エラーメッセージはformat
によりフォーマット
されます。すなわち、最初のフォームは以下と等価です。
(define (errorf fmt . args) (error (apply format #f fmt args))) |
2番目の形式は<error>
以外のエラーコンディションを通知するのに
使えます。condition-type, keyword-argの意味については
error
と同じです。
[SRFI-18] これは、例外事態を通知する基本となるメカニズムです。
この手続きは現在の例外ハンドラを呼び出します。引数conditionは
例外の性質を表現するのに使われ、例外ハンドラに渡されます。
Gaucheの組み込み手続きやライブラリ手続きは常に、<condition>
クラス
もしくはそのサブクラスのインスタンスをconditionとして用いますが、
ユーザは任意のオブジェクトをraise
に渡すこともできます。
渡されたconditionの解釈は例外ハンドラに任されます。
注意事項: いくつかの主流の言語では、例外を「投げる」と制御はそこに
戻りません。Gaucheではraise
から戻って来れるように
セットアップすることが可能です。詳細は例外の処理を
参照してください。
raise
から戻って来ることが無いようにしたい場合は、
<serious-condition>
やそのサブクラスのインスタンスをcondition
としてraise
に渡すのが確実です。
組み込みコンディションのクラス階層についてはコンディションを参照して下さい。
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
[SRFI-34] これはGaucheでのエラー処理の高水準フォームです。
var はシンボルで clause は cond
節と同じ形式です。
つまり、各節は以下の形式のどれかひとつです。
(test expr …)
(test => proc)
最後のclauseは(else expr …)
という形式も許されます。
このフォームは通常の場合には body … を評価し最後の body の式の値を返します。本体の式を評価している最中に例外が 発生した場合、発生した例外を変数 var に束縛し、その後 各節の test 式を評価します。もし、test 式のひとつが 真値を返したとき、その節が上述の最初の形式であれば、対応する expr が評価されます。あるいは、節が二番目の形式であれば、 手続きprocにtestの結果が渡されます。
指定された節の test および expr が評価されるとき、
guard
を呼び出した時点での例外ハンドラが設定されます。つまり、
clause 内部で再び例外が発生した場合、その例外は、外側の
例外ハンドラまたは guard
フォームで処理されます。
もし、どの test も真値を返さず、最後の clause
が
else
節であれば、それに結びつけられた expr が評価されます。
もし、どの test も真値を返さず、else
節がなければ、再び
例外が発生し、外側の例外ハンドラで処理されます。
例外が clause
のどれかで処理された時には、guard
は
それを処理した節の最後の expr の値を返します。
clauseはguard
と同じ動的環境で評価されます。すなわち、
body
中のdynamic-wind
はclauseの評価の前に
巻戻されます。これは低レベル関数のwith-error-handler
や
with-exception-handler
とは異なることに注意してください。
これら低レベル関数では例外ハンドラが呼ばれてから動的環境が巻戻されます。
(let ((z '())) (guard (e (else (push! z 'caught))) (dynamic-wind (lambda () (push! z 'pre)) (lambda () (error "foo")) (lambda () (push! z 'post)))) (reverse z)) ⇒ (pre post caught) (guard (e (else (print 'OUTER) #f)) (with-output-to-string () (print 'INNER) (error "foo"))) ⇒ OUTERを文字列ポートではなくguard実行時の current-output-portに出力。 |
bodyを実行してからcleanupを実行し、bodyの結果を返す。
body内で例外が挙がった場合、その例外がunwind-protect
フォー
ムを抜ける前に、cleanupが実行されます。たとえば、以下のコードで
はなにも問題が起きなければ、start-motor
、drill-a-hole
、
stop-motor
が、この順で呼ばれます。何か不具合が
start-motor
あるいはdrill-a-hole
で起った場合でも、例外が
unwind-protect
を抜ける前にstop-motor
が呼ばれます。
(unwind-protect (begin (start-motor) (drill-a-hole)) (stop-motor)) |
cleanupフォームはunwind-protect
と同じ動的環境で評価されま
す。例外がcleanup内で投げられた場合その例外は、
unwind-protect
フォームの外側で処理されることになります。
このフォームはdynamic-wind
と似ていますが、この2つは動作するレイ
ヤが違いますので混同しないようにしてください。
dynamic-wind
は最下位レイヤのもので、現在の例外ハンドラ、現在の入出力
ポート、パラメータなどを管理するのに用います。
dynamic-wind
のbeforeおよびafterのサンクは
対応する制御フローの遷移が起きたときに必ず呼ばれます。
一方、unwind-protect
はGaucheの例外システムの面倒しか見ません。
unwind-protect
のcleanupはbodyがGaucheの例外を投げた
ときにのみ呼びだされます。上述の例で、unwind-protect
の外側で
補足された継続が呼ばれ、制御がdrill-a-hole
を抜けると、
cleanupは呼ばれません。制御が再びdrill-a-hole
に戻る可能性
があるからです。たとえば、ユーザレベルのスレッドシステムが
call/cc
で実装されているような場合にこのようなことが起こる可能性
があります。
このフォームの名前はCommon Lispから取りました。同様のマクロに
try-finally
というような別の名前を使っているSchemeの処理系もあり
ます。
handlerをアクティブなエラーハンドラにし、thunkを実行します。
thunkが正常に戻ったら、その結果が返されます。
thunkの実行中にエラーが通知されたら、エラーを表す例外オブジェクトを
1引数とするhandlerが、with-error-handler
の継続とともに呼ばれます。
すなわち、with-error-handler
は、handlerが返す値を返します。
handlerがエラーを通知したら、それはwith-error-handler
が
呼ばれたときにインストールされていたハンドラにより処理されます。
handlerが実行される場合の動的な環境は、エラーが起きたときのそれと
同じです。thunk内でdynamic-wind
が使われていたら、
そのafterメソッドはhandlerが戻った後、かつwith-error-handler
が
戻る前に呼ばれます。
註: この手続きを直接使うことはもはや推奨されません。guard
の方が
より安全でポータブルだからです。互換性を保つためまだしばらくは
この手続きを残しますが、この手続きを使っているコードをguard
によって
書き直すことを推奨します。「エラー時に後始末をする」というよくある次のような処理は:
(with-error-handler (lambda (e) (cleanup) (raise e)) (lambda () body …)) |
次のように書き直すことができます。
(guard (e (else (cleanup) (raise e))) body …) |
プログラムで定義した例外ハンドラを設定していないところで例外が発生した 場合以下のようなことが起ります。
EX_SOFTWARE
(70)で終了します。
このレイヤはSRFI-18互換のシンプルな例外メカニズムを提供します。
with-error-handler
のような高次元の構造の振る舞いを、
with-exception-handler
を使って上書きすることができます。
これは諸刃の剣であることに注意して下さい。あなたは独自の例外処理 セマンティクスを構築する自由がありますが、Gaucheシステムは何か 間違いがあっても救ってくれません。システムの高次元のセマンティクスを カスタマイズしたいか、他のSRFI-18準拠のコードを移植している場合にのみ、 これらのプリミティブを使って下さい。
[SRFI-18] 現在の例外ハンドラを返します。
[SRFI-18] handlerは1引数を取る手続きです。この手続きは、handlerを 現在の例外ハンドラにセットし、thunkを呼び出します。
一般的に、エラーのような継続不可能な例外をこの低レベルなメカニズムで
扱いたい場合は、明示的にそのハンドラから制御を移さなければなりません
(前述のwith-error-handler
の説明を参照して下さい)。
raise
は、ハンドラが継続不可能な例外を返したことを検知し、
デフォルトのエラーハンドラメカニズムを使ってエラーを報告しますが、
それは単に安全ネットにしか過ぎません。
handlerはraise
の動的な環境と同じ環境で呼ばれることにも
注意して下さい。したがって、handler内部で例外を発生させると、
再度handlerによって捕捉されます。その例外処理を“外側”の例外
ハンドラへ伝播させるのはプログラマの責任です。
これらの手続きの振る舞いは、次の概念的なSchemeコードによって 説明されるでしょう。
;; 低レベルな例外メカニズムの概念的な実装 ;; %xhは例外ハンドラのリスト (define (current-exception-handler) (car %xh)) (define (raise exn) (receive r ((car %xh) exn) (when (uncontinuable-exception? exn) (set! %xh (cdr %xh)) (raise (make-error "returned from uncontinuable exception"))) (apply values r))) (define (with-exception-handler handler thunk) (let ((prev %xh)) (dynamic-wind (lambda () (set! %xh (cons handler %xh))) thunk (lambda () (set! %xh prev))))) |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
現在のところGaucheには以下の組み込みコンディションクラスの階層があります。 これは、おおよそのところ SRFI-35 および SRFI-36 のコンディションの階層を 反映したものですが、Gauche風のクラス名になっています。対応する SRFI の コンディションタイプがあるものについては、SRFI でのクラス名も使えます。
<condition> +- <compound-condition> +- <serious-condition> | +- <serious-compound-condition> ; also inherits <compound-condition> +- <message-condition> +- <error> ; also inherits <serious-condition> +- <system-error> +- <unhandled-signal-error> +- <read-error> +- <io-error> +- <port-error> +- <io-read-error> +- <io-write-error> +- <io-closed-error> +- <io-unit-error> |
いくつかのコンディションが同時に発生することがあることに注意してください。
たとえば、ファイルの読み込がデバイスの欠陥により失敗した場合は、
<system-error>
および <io-read-error>
の両方からなる
エラーとなるでしょう。
このような場合、合成したコンディション (compound condition) が発生します。
したがって、たとえば、<io-read-error>
が投げられたかどうかをチェック
するのに、単に (is-a? obj <io-read-error>)
を使えばよいというわけ
にはいきません。
後述の「コンディション API」の節を参照してください。
すべてのコンディションクラスはこのクラスのインスタンスです。
このクラスは object-apply
を定義していますので、
コンディションクラスは述語として使うことができます。たとえば、
(<error> obj) ≡ (condition-has-type? obj <error>) |
[SRFI-35] コンディションの階層のルートクラスです。
合成コンディションを表現します。合成コンディションは
make-compound-condition
を用いて1つ以上のコンディションから
生成することができます。このクラスを直接使ってはいけません。
合成コンディションはcondition-has-type?
に対して、
元のコンディションのどれかが、与えられたタイプなら、#t
を返します。
[SRFI-35]
このクラスのコンディションは無視して先を続けることはできない深刻な
状況のためにあります。特に、このタイプのコンディションを raise
したら、それは元には絶対に戻らないと考えて問題ありません。
深刻なコンディションを含む合成コンディションを表現するための
内部クラスです。<compound-condition>
および
<serious-condition>
の両方を継承しています。
make-compound-condition
は深刻なコンディションを含む複数の
コンディションを渡されると、このクラスを使います。このクラスを
直接使ってはいけません。
[SRFI-35] このクラスはメッセージ付のコンディションを表現し、スロットを一つ もっています。
メッセージ
[SRFI-35]
エラーを表します。<serious-condition>
および
<message-condition>
を継承しています。したがって、
message
スロットを持っています。
注意事項: SRFI-35 の&error
コンディションは &serious
のみを継承し、&message
は継承していません。したがって、
このエラーコンディションにメッセージを付与するためには、
合成コンディションを使わなければなりません。Gauche は
主として過去のバージョンとの互換性を確保するために、
ここで多重継承を用いています。
可搬性のあるコードを掛くには、以下のようにメッセージコンディション
付きのエラーコンディションを使うべきです。
(condition (&message (message "Error message")) (&error)) |
<error>
のサブクラス。
システムコールがエラーを返したとき、この型の例外が投げられます。
message
スロットには通常エラーの(strerror(3)
のような)説明が
含まれています。それ以外に、このクラスにはもうひとつ次のような
インスタンススロットがあります。
システムのエラー番号の整数値を持ちます。
エラー番号はシステムによって異なる可能性があります。Gaucheは典型的な
Unixのエラー番号に対して定数を定義している(例: EACCES
, EBADF
)ので、
それを使うと良いでしょう。定義されている定数に関しては
システムへの問い合わせのsys-strerror
の説明を参照してください。
このクラスには対応する SRFI のコンディションタイプがありませんが、
OSの生のエラーコードを取得するのに重要です。いくつかのケースで
このタイプのコンディションは他の、たとえば <io-read-error>
のようなコンディションと合成されます。
<error>
のサブクラス。多くのシグナルのデフォルトハンドラは
このコンディションを投げます。詳しくはシグナルの処理を
参照してください。
受け取ったシグナル番号を示す整数値。典型的なシグナル番号については 定数が定義されています。シグナルとシグナルセットを参照のこと。
[SRFI-36]
<error>
のサブクラス。リーダがS式を読み込み中に、字句エラー
または構文エラーを検出したとき、この型のコンディションが投げられます。
リーダがS式を読みこんでいたポート。
(註: SRFI-36 の &read-error
はこのスロットを定義していません。
ポータブルなプログラムを書く場合はこのスロットを使わないで下さい)。
リーダがこのエラーを発生させたときの入力行カウント(1がベース)。 リーダが行カウントを保持しないポートから読み込むときには、-1 となる。
これらのスロットは、SRFI-36 の &read-error
で定義されています。
今のところ、これらのスロットは常に #f
を保持するようになっています。
[SRFI-36]
I/O エラーのベースとなるクラス。<error>
を継承しています。
[SRFI-36]
ポート関連の I/O エラー。<io-error>
を継承しています。
エラーを起したポートを保持。
[SRFI-36]
ポートから読み込み中の I/O エラー。<port-error>
を継承しています。
[SRFI-36]
ポートへの書き出し中の I/O エラー。<port-error>
を継承しています。
[SRFI-36]
クローズされたポートで読み込み/書き出しをしようしたときの I/O エラー。
<port-error>
を継承しています。
対象となるポートでサポートされていない単位での読み/書き要求
(たとえば、キャラクタ専用ポートでのバイナリ I/O 要求)の際の I/O エラー。
<port-error>
を継承しています。
[SRFI-35+]
新しいコンディションタイプを定義します。Gaucheでは、コンディションタイプは
クラスであり、そのメタクラスは <condition-meta>
です。
name が新しいタイプの名前になり、この名前の変数が作成された
コンディションタイプに束縛されます。supertype はこのコンディション
タイプのスーパータイプ(直接のスーパークラス)の名前です。コンディション
タイプは <condition>
を継承するか、その子孫を継承しなければ
なりません。(この形式では、多重継承を指定することはできません。
一般的にいって、コンディションタイプの階層の中では多重継承は避ける
べきです。そのかわりに、合成コンディションを使えます。合成コンディションは
多重継承を使いません。)
変数 predicate はこのコンディションタイプ用の述語手続きに 束縛されます。
各 field-spec
は (field-name accessor-name)
の形式で
このコンディションは、フィールド名は field-name で決まります。
変数 accessor-name はそのフィールドにアクセスする手続きに
束縛されます。Gauche では、それぞれのフィールドは生成された
クラスのスロットとなります。
Gaucheはsrfi-35を拡張して、predicateやaccessor-nameを
定義する必要が無い場合はその位置に#f
を指定できるようにしています。
accessor-nameが必要無い場合はそれを省略することもできます。
define-condition-type
がクラス定義に展開される際に、
各スロットは:init-keyword
スロットオプションにスロット名と
同名のキーワードを取るように定義されます。
[SRFI-35]
objがコンディションタイプである場合で、その場合にかぎり、
#t
を返します。Gauche では (is-a? obj <condition-meta>)
と同じです。
[SRFI-35] 新しいコンディションタイプを生成する手続き版です。
[SRFI-35]
コンディションタイプ type のコンディションを生成し、
field-name
および value
のペアで指定されたように
フィールドを初期化します。
[SRFI-35]
obj がコンディションである場合で、その場合にかぎり、
#t
を返します。Gauche では (is-a? obj <condition>)
と
同じです。
[SRFI-35]
obj がコンディションタイプ type に属している場合で、その
場合にかぎり、#t
を返します。合成コンディションがあるので、
これは、is-a?
と同じではありません
[SRFI-35]
condition のフィールド field-name の値を検索します。
condition が合成コンディションであれば、元のコンディションの
フィールドにアクセスできます。もし、複数の元のコンディションが、
field-name を持つ場合には、最初に make-compound-condition
に渡されたものが優先されます。
コンディションのフィールドにアクセスするには、slot-ref および
ref の両方あるいはどちらかを使えます。合成コンディションでは、
slot-missing
メソッドが定義されますので、slot-ref は
あたかも、合成コンディションが元になったコンディションの全てのスロットを
もつかのように振舞います。しかしながら、condition-ref
を
使う方が可搬性が増します。
[SRFI-35]
condition0 condition1 … のすべてを持つ合成コンディション
を返します。返されたコンディションのフィールドは、与えられたコンディション
のすべてのフィールドの和集合になります。同じ名前のフィールドを持つ
コンディションがある場合には最初に与えられものが優先されます。
返されたコンディションは元になったコンディションのすべてのタイプの
コンディションタイプをもつことになります。
(これは多重継承ではありません。上の <compound-condition>
を参照)
[SRFI-35] condition はコンディションで、condition-typeタイプで なければなりません。この手続きは condition-type のコンディション を返し、condition からとりだされた値のフィールドを持ちます。
[SRFI-35]
コンディションを生成するのに便利なマクロ。
合成されたコンディションも生成できます。
Type-field-binding は、
(condition-type (field-name value-expr) …)
という形式になります。
(condition (type0 (field00 value00) ...) (type1 (field10 value10) ...) ...) ≡ (make-compound-condition (make-condition type0 'field00 value00 ...) (make-condition type1 'field10 value10 ...) ...) |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] |
This document was generated by Shiro Kawai on November, 22 2009 using texi2html 1.78.