GNU Emacs 32.0.50 (9008bf64c3) のマニュアルを PLaMo 翻訳で機械翻訳したものです。誤訳を含むことがあります。原文: https://www.gnu.org/software/emacs/manual/html_node/elisp/Examples-of-Catch.html ・ emacs-doc.conao3.com

11.7.2 catch と throw の例

catch と throw の使い方の一つに、二重にネストされたループから抜けるというものがあります。(ほとんどの言語では、これは goto を用いて行われます。)ここでは、0から9まで変化する i と j に対して (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))))))

If foo ever returns non-nil, we stop immediately and return a list of i and j. If foo always returns nil, the catch returns normally, and the value is nil, since that is the result of the while.

ここでは、2つの戻り点を同時に示す、わずかに異なる2つのトリッキーな例を挙げます。まず、同じタグ hack を持つ2つの戻り点です:

(defun catch2 (tag)
  (catch tag
    (throw 'hack 'yes)))
⇒ catch2

(catch 'hack
  (print (catch2 'hack))
  'no)
⊣ yes
⇒ no

両方の戻り値に throw と一致するタグがあるため、内側の catch2 で設定された方へと進みます。したがって、catch2 は値 yes を通常通り返し、この値が出力されます。最後に、外側の catch にある2番目のボディフォームである 'no が評価され、外側の catch から返されます。

それでは、catch2に与えられた引数を変更しましょう:

(catch 'hack
  (print (catch2 'quux))
  'no)
⇒ yes

戻り値の箇所はまだ2つありますが、今回は外側の箇所にのみタグ hack が付いており、内側の箇所には代わりにタグ quux が付いています。したがって、throw によって外側の catch が値 yes を返します。関数 print が呼び出されることはなく、ボディフォーム 'no が評価されることもありません。