Re: New draft (#8) and last call for comments on SRFI 255: Restarting conditions Marc Nieper-Wißkirchen (15 Dec 2024 21:08 UTC)

Re: New draft (#8) and last call for comments on SRFI 255: Restarting conditions Marc Nieper-Wißkirchen 15 Dec 2024 21:08 UTC

Am Fr., 13. Dez. 2024 um 23:27 Uhr schrieb Wolfgang Corcoran-Mathe
<xxxxxx@sigwinch.xyz>:
>
> Marc,
>
> Thanks for your thoughts.
>
> On 2024-12-13 20:52 +0100, Marc Nieper-Wißkirchen wrote:
> > Related to this is that the examples of "with-current-interactor" can
> > be misleading. One may think that at every critical place, one needs
> > to wrap with "with-current-interactor".
>
> Good point. Since it’s just boilerplate, I think it can be removed from
> the examples.
>
> > A problem that hasn't occurred to me yet is that the original
> > condition that triggered the addition of a restarter should remove the
> > original condition from the compound. Semantically, adding a restarter
> > should mean that the condition is handled (unless the restarter with
> > tag "re-raise the condition" is invoked). If not, say, if an assertion
> > violation is raised, all procedure calls in the call stack that are
> > protected via "restartable" would present a restarter (even with the
> > same tag) to the user. In case of a deep recursion, this would also
> > make the interface unusable.
>
> As I see it, raising a restarter doesn’t mean the original condition
> has been handled, but that one possible way of handling it is being
> proposed. The condition is handled when the user chooses a restarter
> and ‘restart’ is invoked. Removing the original condition also makes
> it impossible to report anything about the triggering condition to the
> user, aside from whatever is included in the restarters themselves.
> All told, this leaves the user in the dark: “Something went wrong—no,
> we won’t tell you what, and everything’s fine now that you’re here.
> What do we do next?”

I agree that raising a restarter does not mean that the current
condition is handled, but that does not mean that the current
continuation could not be moved into the restarter because now it is
the restarter condition that has to be handled. There should be an
option to abort a restarter, meaning to reraise the original condition
to handle it further up in the handler stack.

As long as the original condition is still somewhere, it is possible
to show it to the user.

The current model has the problem that handlers further up the handler
stack cannot know whether the condition they observed will eventually
have been handled or not. Consider an I/O error. Down the handler
stack, a restarter condition may be added. Further up the handler
stack, there may be another handler catching the I/O error (+ the
restarter, which it doesn't handle) and that handler may decide to
delete a file to do some partial clean-up the erroneous condition
before re-raising the compound condition.

>
> > Then there is a serious problem I haven't thought about before:
> > "define-restartable" kills all proper tail calls; if a procedure
> > protected by "define-restartable" is part of a recursive algorithm, it
> > will never tail-call. This is bad; it should be safe to replace
> > "define" with "define-restartable" without changing the semantics. I
> > have to think of a solution.
>
> You’re right. This seems hard to solve. I will think about it some
> more, too, but I suspect we may have to remove ‘define-restartable’.
>
> with-exception-handler’s non-tail-position semantics also make it
> impossible to specify tail position for the body of a ‘restarter-guard’
> form, sadly.
>
> > I have one more question: Can you explain why the
> > restarter-condition-predicate could be helpful?
>
> Some restarters may only be relevant to certain situations. I had I/O
> conditions especially in mind here. A program that reads from a port
> might want to offer a restarter that changes port settings before
> retrying a read operation, for example. This would probably make sense
> only if a condition satsifying ‘io-read-error?’ or a similar predicate
> had been raised.

This is probably too coarse-grained in practise.

Apart from that, a restarter is added by a handler; in your example,
the restarter would have only been added in case of an io-read-error?.

Best,

Marc