summaryrefslogtreecommitdiff
path: root/devdocs/elisp/examples-of-catch.html
blob: d10b0589a4ed761ce5f73423fb7b085f30fd7a62 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
 <h4 class="subsection">Examples of catch and throw</h4> <p>One way to use <code>catch</code> and <code>throw</code> is to exit from a doubly nested loop. (In most languages, this would be done with a <code>goto</code>.) Here we compute <code>(foo <var>i</var> <var>j</var>)</code> for <var>i</var> and <var>j</var> varying from 0 to 9: </p> <div class="example"> <pre class="example">(defun search-foo ()
  (catch 'loop
    (let ((i 0))
      (while (&lt; i 10)
        (let ((j 0))
          (while (&lt; j 10)
            (if (foo i j)
                (throw 'loop (list i j)))
            (setq j (1+ j))))
        (setq i (1+ i))))))
</pre>
</div> <p>If <code>foo</code> ever returns non-<code>nil</code>, we stop immediately and return a list of <var>i</var> and <var>j</var>. If <code>foo</code> always returns <code>nil</code>, the <code>catch</code> returns normally, and the value is <code>nil</code>, since that is the result of the <code>while</code>. </p> <p>Here are two tricky examples, slightly different, showing two return points at once. First, two return points with the same tag, <code>hack</code>: </p> <div class="example"> <pre class="example">(defun catch2 (tag)
  (catch tag
    (throw 'hack 'yes)))
⇒ catch2
</pre>

<pre class="example">(catch 'hack
  (print (catch2 'hack))
  'no)
-| yes
⇒ no
</pre>
</div> <p>Since both return points have tags that match the <code>throw</code>, it goes to the inner one, the one established in <code>catch2</code>. Therefore, <code>catch2</code> returns normally with value <code>yes</code>, and this value is printed. Finally the second body form in the outer <code>catch</code>, which is <code>'no</code>, is evaluated and returned from the outer <code>catch</code>. </p> <p>Now let’s change the argument given to <code>catch2</code>: </p> <div class="example"> <pre class="example">(catch 'hack
  (print (catch2 'quux))
  'no)
⇒ yes
</pre>
</div> <p>We still have two return points, but this time only the outer one has the tag <code>hack</code>; the inner one has the tag <code>quux</code> instead. Therefore, <code>throw</code> makes the outer <code>catch</code> return the value <code>yes</code>. The function <code>print</code> is never called, and the body-form <code>'no</code> is never evaluated. </p><div class="_attribution">
  <p class="_attribution-p">
    Copyright &copy; 1990-1996, 1998-2022 Free Software Foundation, Inc. <br>Licensed under the GNU GPL license.<br>
    <a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Examples-of-Catch.html" class="_attribution-link">https://www.gnu.org/software/emacs/manual/html_node/elisp/Examples-of-Catch.html</a>
  </p>
</div>