next up previous contents index
: ハンドラの探索順序 : ハンドラ定義機能 : 大域ハンドラの定義   目次   索引

局所ハンドラの定義

(handler-bind ((《コンディションクラス$_{1}$》《ハンドラ$_{1}$》)$\cdots$ (《コンディションクラス$_{n}$》《ハンドラ$_{n}$》)) 《本体》) 【マクロ】

《コンディションクラス》 に対して,与えられた各々のハンドラをバインド し,与えられたハンドラの束縛が有効である動的スコープの中で,《本体》を 実行する. 各ハンドラは,本体実行中に与えられたコンディションを処理するために用い られる関数であり,この関数は唯一の引数,すなわち通知されたコンディショ ンを受け取る.

《本体》の評価中にコンディションが通知された場合,バインドされている ハンドラの中から適切なハンドラが探索され,そのハンドラに制御が移る. 《ハンドラ》の評価結果が,コンディションを通知した関数の値となり, 処理を続行する. 《本体》の評価中にコンディションが通知されなかった場合には,《本体》の 最後の式の評価結果が handler-bind フォームの結果として返される.

例:
次の例は引数 a b cの3つを受けとり, ${\tt a}+{\tt b}/{\tt c}$を計算する関数 fooを定義している. 式 (+ a (/ b c))を評価中にコンディション division-by-zeroまたは, コンディション errorのエラーが通知されたら,それぞれのコンディション に対して定義されているハンドラに制御が移る. コンディション division-by-zeroあるいは,そのサブクラスのコンディション が通知された場合,コンディションを通知した関数の返値として, 大域変数 *infinity*の値を用いる. コンディション errorあるいは,そのサブクラスのコンディションが通知 された場合,記号 error!を返す.

> (define *infinity* 0)
*infinity*
> (define (foo a b c)
    (handler-bind ((division-by-zero
                     (lambda (c)
                       (format *error-output* 
                               "Use value of *infinity*, ~a, "
                               *infinity*)
                       (format *error-output* "in ~a.~%" 
                               (slot-value c 'function))
                       *infinity*))
                   (error (lambda (c) 'error!)))
      (+ a (/ b c))))
foo
> (foo 10 5 0)
Use value of *infinity*, 0, in #<function />.
10
> (set! *infinity* 'infinity)
infinity
> (foo 10 5 0)
Use value of *infinity*, infinity, in #<function />.
error!
>

(handler-case 《式》 (《コンディションクラス$_{1}$》([《変数$_{1}$》])《ハンドラ本体$_{1}$》)$\cdots$ (《コンディションクラス$_{n}$》([《変数$_{n}$》])《ハンドラ本体$_{n}$》)) 【マクロ】

多数の指定されたハンドラがバインドされている文脈の中で与えられた 《式》を評価する. もし,《式》を評価中にコンディションが通知され,それに適合するハンドラ がバインドされているならば,制御をハンドラ本体に移す. その際に与えられている《変数》に通知されたコンディションがバインドされ, その《変数》は,ハンドラの本体中で参照することができる. ハンドラの本体中でバインドされたコンディションを参照しない場合は, 《変数》を省略することができる. 《ハンドラ本体》の評価結果が,コンディションを通知した関数の結果となり 処理が続行される. もし,コンディションが通知されなかった場合には,《式》の評価結果が handler-caseフォームの結果として返される.

例:
handler-bindにおける例は, handler-caseを用いると以下の ように書ける.

(define (foo a b c)
  (handler-case (+ a (/ b c))
    (division-by-zero (c)
      (format *error-output* 
              "Use value of *infinity*, ~a, "
              *infinity*)
      (format *error-output* "in ~a.~%" 
              (slot-value c 'function))
      *infinity*)
    (error () 'error!)))



Tsuneyasu KOMIYA 平成14年2月22日