elisp: Examples of Catch

 
 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.