Common Lisp the Language, 2nd Edition


next up previous contents index
Next: Generalized Restarts Up: Survey of Concepts Previous: Restart Functions

29.3.9. Comparison of Restarts and Catch/Throw

change_begin
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).
change_end



next up previous contents index
Next: Generalized Restarts Up: Survey of Concepts Previous: Restart Functions


AI.Repository@cs.cmu.edu