Next: Errors, Previous: Catch and Throw, Up: Nonlocal Exits [Contents][Index]
catchとthrownの例2重にネストされたループから脱出する1つの方法は、catchとthrowを使うことです(これはほとんどの言語ではgotoにより行なわれるだろう)。ここではiとjを0から9に変化させて、(foo
i j)を計算します:
(defun search-foo ()
(catch 'loop
(let ((i 0))
(while (< i 10)
(let ((j 0))
(while (< j 10)
(if (foo i j)
(throw 'loop (list i j)))
(setq j (1+ j))))
(setq i (1+ i))))))
fooが非nilをリターンしたら即座に処理を中止して、iとjのリストをリターンしています。fooが常にnilをリターンする場合には、catchは通常どおりリターンして、その値はwhileの結果であるnilとなります。
以下では2つのリターン位置を一度に表す、微妙に異なるトリッキーな例を2つ示します。まず同じタグhackにたいして2つのリターン位置があります:
(defun catch2 (tag)
(catch tag
(throw 'hack 'yes)))
⇒ catch2
(catch 'hack (print (catch2 'hack)) 'no) -| yes ⇒ no
どちらのリターン位置もthrowにマッチするタグをもつので内側のもの、つまりcatch2で確立されたcatchへgotoします。したがってcatch2は通常どおり値yesをリターンして、その値がプリントされます。最後に外側のcatchの2番目のbody、つまり'noが評価されて外側のcatchからそれがリターンされます。
ここでcatch2に与える引数を変更してみましょう:
(catch 'hack (print (catch2 'quux)) 'no) ⇒ yes
この場合も2つのリターン位置がありますが、今回は外側だけがタグhackで、内側はかわりにタグquuxをもちます。したがってthrowにより、外側のcatchが値yesをリターンします。関数printが呼び出されることはなくbodyのフォーム'noも決して評価されません。