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