Next: Errors, Previous: Catch and Throw, Up: Nonlocal Exits [Contents][Index]
catch and throw2重にネストされたループから脱出する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をreturnした場合、即座に処理を止めて、iとjのリストをreturnしています。fooが常にnilをreturnする場合、catchは通常どおりreturnし、その値はwhileの結果であるnilとなります。
以下では、2つのreturn位置を1度に表す、微妙に異なるトリッキーな例を2つ示します。最初に、同じタグhackにたいする2つのreturn位置があります:
(defun catch2 (tag)
(catch tag
(throw 'hack 'yes)))
⇒ catch2
(catch 'hack (print (catch2 'hack)) 'no) -| yes ⇒ no
どちらのreturn位置もthrowにマッチするタグをもつので、内側のもの、つまりcatch2で確立されたものにgotoします。したがってcatch2は通常どおり値yesをreturnするので、その値がプリントされます。最後に外側のcatchの2番目のbody、つまり'noが評価されて、外側のcatchからそれがreturnされます。
ここで、catch2に与える引数を変更してみます:
(catch 'hack (print (catch2 'quux)) 'no) ⇒ yes
この場合も2つのreturn位置がありますが、今回は外側だけがタグhackをもち、内側のものは、かわりにタグquuxをもちます。したがって、throwにより、外側のcatchが値yesをreturnします。関数printが呼び出されることはなく、bodyのフォーム'noも決して評価されません。