Common Lisp the Language, 2nd Edition

Next: Generalized Restarts Up: Survey of Concepts Previous: Restart Functions

## 29.3.9. Comparison of Restarts and Catch/Throw

One important feature that `restart-case` (or `restart-bind`) offers that `catch` does not is the ability to reason about the available points to which control might be transferred without actually attempting the transfer. One could, for example, write

    (ignore-errors (throw ...))

which is a sort of poor man's variation of

    (when (find-restart 'something)
      (invoke-restart 'something))

but there is no way to use `ignore-errors` and `throw` to simulate something like

    (when (and (find-restart 'something)
               (find-restart 'something-else))
      (invoke-restart 'something))

or even just

    (when (and (find-restart 'something)
               (yes-or-no-p "Do something? "))
      (invoke-restart 'something))

because the degree of inspectability that comes with simply writing

    (ignore-errors (throw ...))

is too primitive-getting the desired information also forces transfer of control, perhaps at a time when it is not desirable.

Many programmers have previously evolved strategies like the following on a case-by-case basis:

    (defvar *foo-tag-is-available* nil)

    (defun fn-1 ()
      (catch 'foo
        (let ((*foo-tag-is-available* t))
          ... (fn-2) ...)))

    (defun fn-2 ()
      ...
      (if *foo-tag-is-available* (throw 'foo t))
      ...)

The facility provided by `restart-case` and `find-restart` is intended to provide a standardized protocol for this sort of information to be communicated between programs that were developed independently so that individual variations from program to program do not thwart the overall modularity and debuggability of programs.

Another difference between the restart facility and the `catch`/`throw` facility is that a `catch` with any given tag completely shadows any outer pending `catch` that uses the same tag. Because of the presence of `compute-restarts`, however, it is possible to see shadowed restarts, which may be very useful in some situations (particularly in an interactive debugger).

Next: Generalized Restarts Up: Survey of Concepts Previous: Restart Functions