% Macro HANDLER-BIND
Macro HANDLER-BIND
handler-bind
({
binding}
*) form* => result*
binding::= (type handler)
type - 型指定子
handler - フォーム。評価されたらhandler-functionを生成します。
handler-function - ひとつの引数を取る関数指定子
form - 暗黙のprogn
result - formによる返却値
handlerが束縛されている効果がある 動的環境の下でformを評価します。
各handlerは評価されてhandler-functionにならなければならず、 formを評価している間は、 指定されたtypeのコンディションが捕捉されたときに その関数が使用されます この関数はひとつの引数を受け取れなければならず、 その引数には通知されたコンディションが渡されます。
もし複数のhandlerの束縛が指定されたとき、
handlerの束縛は、順番に上から下へ
(視覚的にtypecase
に似た方法で)
マッチするものを探します。
もし適切な型が見つかったときは、
その関連するハンドラーは、
これらのhandlerの束縛が見えないような動的環境下で
(再帰的なエラーを回避するため)実行されます。
もしhandlerが下がると、他に続くhandlerを探します。
もし適切なhandlerが無かったときは、
動的に囲まれた部分から他のハンドラを探します。
もし外側にもhandlerがなかったときは、
signal
は戻るか、あるいはerror
はデバッガーに入ります。
下記のコードは、もしボディ部でunbound
な変数のエラーが通知されたら
(そしてハンドラーの介入が無かったら)、
最初の関数が呼ばれます。
(handler-bind ((unbound-variable #'(lambda ...))
(error #'(lambda ...)))
...)
もしそれ以外の何らかのエラーが通知されたら、 二番目の関数が呼び出されます。 いずれの場合も、関連する関数のコードを実行している間委は、 どちらのハンドラーもアクティブになりません。
(defun trap-error-handler (condition)
(format *error-output* "~&~A~&" condition)
(throw 'trap-errors nil))
(defmacro trap-errors (&rest forms)
`(catch 'trap-errors
(handler-bind ((error #'trap-error-handler))
,@forms)))
(list (trap-errors (signal "Foo.") 1)
(trap-errors (error "Bar.") 2)
(+ 1 2))
>> Bar.
=> (1 NIL 3)
"FOO"
は印刷されませんが、
これはsignal
によってsimple-condition
を通知したためであり、
型error
ではないため、
trap-errors
によって用意されたerror
のハンドラーが
トリガーされないのです。
なし。
なし。
なし。
なし。