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の名前はレキシカルスコープです。