Next: Errors, Previous: Catch and Throw, Up: Nonlocal Exits [Contents][Index]

#### 10.6.2 Examples of `catch` and `throw`

One way to use `catch` and `throw` is to exit from a doubly nested loop. (In most languages, this would be done with a `goto`.) Here we compute `(foo i j)` for i and j varying from 0 to 9:

    (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`.

Here are two tricky examples, slightly different, showing two return points at once. First, two return points with the same tag, `hack`:

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

    (catch 'hack
      (print (catch2 'hack))
      'no)
    âŠ£ yes
    ⇒ no

Since both return points have tags that match the `throw`, it goes to the inner one, the one established in `catch2`. Therefore, `catch2` returns normally with value `yes`, and this value is printed. Finally the second body form in the outer `catch`, which is `'no`, is evaluated and returned from the outer `catch`.

Now let’s change the argument given to `catch2`:

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

We still have two return points, but this time only the outer one has the tag `hack`; the inner one has the tag `quux` instead. Therefore, `throw` makes the outer `catch` return the value `yes`. The function `print` is never called, and the body-form `'no` is never evaluated.

Next: Errors, Previous: Catch and Throw, Up: Nonlocal Exits [Contents][Index]