Am So., 9. Okt. 2022 um 12:41 Uhr schrieb Shiro Kawai <shiro.ka...@gmail.com>: > > 1. Common Lisp's unwind-protect allows multiple cleanup forms. Personally I > don't see much benefit of allowing it, but to avoid confusions, we may adopt > the same API.
That's a good point. (I missed initially that there can be more than one cleanup form.) Does CL execute the cleanup forms in order of their appearance? > 2. This is more involved. The cleanup forms of unwind-protect are literally > for cleaning up, e.g. releasing resources. This poses an issue in Scheme; > with continuations, control can reenter protected-form. Executing > cleanup-forms in the after thunk of dynamic-wind invalides such applications > as coroutines. Please note the appearance of `call-with-continuation-barrier` in my proposed definition. It is defined in SRFI 226. It is an error to reinstate a continuation barrier, so escaping continuation in my definition are allowed (triggering the cleanup forms), but returning through a captured continuation is not. Does it solve your second issue? > I don't think there's a clear solution, for there's no way to know for sure > if the control transfer out of protected-form is final. In Gauche, we > transfer (unwind-protect protected-form cleanup-forms ...) to roughly this > code: > > ==== > (let ((done #f)) > (define (cleanup) > (unless done > (set! done #t) > cleanup-form ...)) > (guard (e ((condition-has-type? e <serious-condition>) > (cleanup) > (raise e)) > (else (raise e))) > (receive r protected-form > (cleanup) > (apply values r)))) > ==== > > This code relies on some Gauche-specific behaviors. > (Actual code is a lot more messy for it accesses Gauche runtime internals) > > - Gauche's exception system predates srfi-34 etc, and our <serious-condition> > isn't allowed to be continuable. We only call cleanup forms when a serious > condition is thrown (or protected form exits normally). > - If controls goes out with other type of conditions, cleanup forms aren't > executed, for the condition may be continuable. It's up to the user to deal > with the consequences. If the cleanup forms are so important, translate > conditions to serious ones in protected forms. > - Control transfers other than raise/error don't trigger cleanup forms. It's > up to the user to ensure such control should return to the protected-form > eventually. > - If a continuation is captured in protected-form, and it exits normally, and > then the control reenters to protected-form again, cleanup forms are no > longer invoked. Supposedly it has already committed irreversible action. > The second execution of protected-form may access to the already released > resources and causes an error; it's up to the user to deal with the > consequence. > > I know it is a pretty leaky abstraction. But executing cleanup forms in the > after thunk won't coexist with continuation based coroutines. > > > > > > > > > > > On Sat, Oct 8, 2022 at 11:56 PM Marc Nieper-Wißkirchen > <marc.nie...@gmail.com> wrote: >> >> John Cowan suggested that SRFI 226 should include a version of Common >> Lisp's unwind-protect suitable for Scheme. >> >> In [1], I replied after some discussion with the following proposal >> for a definition of a Scheme unwind-protect: >> >> (define-syntax unwind-protect >> (syntax-rules () >> ((unwind-protect protected-form cleanup-form) >> (call-with-continuation-barrier >> (lambda () >> (dynamic-wind >> (lambda () (values)) >> (lambda () protected-form) >> (lambda () cleanup-form))))))) >> >> As I think it is essential to get this famous form right when included >> in a fundamental SRFI like SRFI 226, I would like to hear more >> opinions on the above form. >> >> (It should be noted, that Scheme procedures like >> `call-with-input-file` are not based on unwind-protect semantics.) >> >> Should there be no consensus on unwind-protect, it is probably better >> to reserve an extra SRFI for it (which, in turn, can depend on SRFI >> 226). >> >> Thanks for taking a look, >> >> Marc >> >> -- >> >> [1] https://srfi-email.schemers.org/srfi-226/msg/20888154/