On Sat, Jul 11, 2020 at 6:14 AM Chris Vine <vine35792...@gmail.com> wrote:
> (To answer the question in your > following email, continuable exceptions are in some sense analogous to > common lisp restarts.) Continuable and non-continuable in Scheme are exactly like CL raise and error (and its variants), except that the machinery is different. Restarts are another matter, independent of the condition system (though often considered with it). I have a pre-SRFI for them at < https://github.com/johnwcowan/r7rs-work/blob/master/RestartsCowan.md>, similar to but simpler than the CL restart system, and using first-class restarts. It currently lacks restart-case. The point arising from this is that in the case of a non-continuable > exception the handler procedure passed to with-exception-handler must > not return, or a &non-continuable exception will be raised when > control does attempt to return. > In CL the exact machinery is different: a CL handler refuses to handle a condition by returning. A continuable exception must use a non-local exit to get back to the signaler, whereas an unhandled non-continuable exception drops into the semi-standardized facility called the debugger. > R6RS/R7RS's guard form is a wrapper for this which also > incorporates a cond form to enable different exception types to be > handled by different handlers. > Is the intention to provide `guard` in Guile 3.x? I think common lisp restarts are by and large useless. They rely on > the assumption that the caller of a procedure which throws knows better > how to handle an exception arising in that procedure than the procedure > itself. That is rarely the case. Usually the code at the site of the > error should do what it can to remedy the problem and then (if it cannot > be fully rectified) throw an exception which unwinds the stack, for the > exception to be picked up elsewhere. Here's a straightforward example of restarts in action. Suppose a library reads a file in a format known to itself, performs some complex in-memory transformations of the data, and then writes the data to another or the same file in the same format. Of course the files may be inaccessible to the library for whatever reasons, and some kind of recovery is needed. The usual approach is to export three procedures: one to read the input file and return the data in an opaque internal format, one to process the data and return the transformed data, and one to write the output file. Any of them may throw exceptions if something goes wrong. However, this exposes the internal data format to the caller, and requires the caller to strictly follow the input-process-output sequence of calls, a tiny design pattern. With continuable exceptions plus restarts, however, there can be just one exposed procedure which is passed an input file name and an output file name which does it all. If any of the I/O components fail, a continuable exception can be raised which when handled invokes a restart (of type "use-value") with the name of a replacement file name to use instead. As a result, the opaque data is now always concealed from the caller, but a write failure does not require the already-transformed data to be recomputed. Just as a condition communicates information from a signaler (which knows what is wrong) to a handler (which knows what to do), a restart communicates information from the handler (which knows what should be done) back to the signaler (which knows how to do it). John Cowan http://vrici.lojban.org/~cowan co...@ccil.org All Norstrilians knew that humor was "pleasurable corrigible malfunction". --Cordwainer Smith, Norstrilia