Special Operator CATCH
catch
tag form* => result*
tag - catch
のタグ、評価されます。
form - 暗黙のprogn
result - もしformが普通に終了したときはformの返却値が、 もしtagへのthrow
が発生した時はthrow
の値が返却されます。
catch
は、throw
による非局所的な制御の転送先として使われます。 tagはthrow
が制御の転送するときに、 catch
を探すときに使われます。 (catch 'foo form)
は(throw 'foo form)
に補足されますが、 (throw 'bar form)
では捕捉されません。
catch
はの実行の順番は次のとおりです。
tagが評価されます。 それはcatch
の名前として保存されます。
それからformが暗黙のprognとして評価されます。 もしthrow
が発生しなかったら、最後のformの値が返却されます。
もしthrow
がformのどれかの実行中に発生したとき、 throw
の引数のタグとeq
で一致する、 もっとも近くで確立したtagのcatch
に制御が転送されます。 それ以上のformの評価は生じません。
catch
によって確立されたタグは、 結果が返される直前に解除されます。
もしformのどれかの実行中に、 catch
タグとeq
で一致するタグを持つthrow
が実行されたとき、 throw
で指定された値がそのタグを持つ動的にもっとも近くで確立された catch
フォームの結果として返されます。
catch
とthrow
の仕組みは、 throw
がcatch
のレキシカルスコープの中にいなくても動作します。 throw
は、対応するtagを持つcatch
のボディ部の評価の 動的エクステント内で実行されなければなりません。
catch 'dummy-tag 1 2 (throw 'dummy-tag 3) 4) => 3
(catch 'dummy-tag 1 2 3 4) => 4
(defun throw-back (tag) (throw tag t)) => THROW-BACK
(catch 'dummy-tag (throw-back 'dummy-tag) 2) => T
(
;; このサンプルは対応するBLOCKのサンプルの対比です
catch 'c
(flet ((c1 () (throw 'c 1)))
(catch 'c (c1) (print 'unreachable))
(2)) => 2
なし。
適切なcatch
のtagがないときにthrow
が実行されたときは、 型control-error
のエラーが発生します。
throw
, 3.1. 評価
慣例としてtagにはシンボルが使われますが、どんなオブジェクトで許されます。 しかし比較にはeq
が用いられますので、数は使うべきではありません。
catch
とblock
の違いは、 catch
のタグは動的スコープであるのに対して、 block
の名前はレキシカルスコープです。