guile-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: "Missing" libraries/concepts found in other languages/ecosystems?


From: John Cowan
Subject: Re: "Missing" libraries/concepts found in other languages/ecosystems?
Date: Sat, 11 Jul 2020 14:20:22 -0400

On Sat, Jul 11, 2020 at 6:14 AM Chris Vine <vine35792468@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        cowan@ccil.org
All Norstrilians knew that humor was "pleasurable corrigible malfunction".
        --Cordwainer Smith, Norstrilia


reply via email to

[Prev in Thread] Current Thread [Next in Thread]