|
call/cc necessitates dynamic-wind?
Eleanor Bartle
(01 Jan 2026 03:24 UTC)
|
||
|
Re: call/cc necessitates dynamic-wind?
Marc Nieper-Wißkirchen
(01 Jan 2026 12:48 UTC)
|
||
|
(missing)
|
||
|
(missing)
|
||
|
Re: call/cc necessitates dynamic-wind?
Eleanor Bartle
(02 Jan 2026 14:35 UTC)
|
||
|
Re: call/cc necessitates dynamic-wind?
Marc Nieper-Wißkirchen
(02 Jan 2026 15:07 UTC)
|
||
|
Re: call/cc necessitates dynamic-wind?
Eleanor Bartle
(03 Jan 2026 00:09 UTC)
|
||
|
Re: call/cc necessitates dynamic-wind?
Marc Nieper-Wißkirchen
(03 Jan 2026 09:36 UTC)
|
||
|
Re: call/cc necessitates dynamic-wind?
Eleanor Bartle
(04 Jan 2026 23:01 UTC)
|
||
|
Re: call/cc necessitates dynamic-wind?
Marc Nieper-Wißkirchen
(09 Jan 2026 10:14 UTC)
|
||
|
Re: call/cc necessitates dynamic-wind?
Marc Nieper-Wißkirchen
(02 Jan 2026 08:49 UTC)
|
||
|
Re: call/cc necessitates dynamic-wind? Marc Nieper-Wißkirchen (02 Jan 2026 10:58 UTC)
|
||
PPS A different answer leading to a similar conclusion is that it goes
against Scheme's minimalism to provide two features when one suffices.
In R5RS, there was only one way to deal with the dynamic environment,
namely the already-mentioned ‘dynamic-wind’. In R[67]RS, this changed
with the addition of the exception handler stack. We now have a second
way to handle dynamically bound variables (aka parameters):
(define-condition-type &get-param &condition
make-get-param-condition get-param-condition?)
(define (param)
(raise-continuable (make-get-param-condition))
(define (with-param val thunk)
(with-exception-handler
(lambda (exc)
(cond
[(get-param-condition? exc) val]
[else (raise-continuable exc)]))
thunk))
What is not yet possible with the handler stack of R[67]RS is the
execution of arbitrary code when the stack is wound/unwound, as is
possible with ‘dynamic-wind’. But such uses have been criticised much
anyway because they make coroutines/generators implemented with
‘call/cc' too costly. In any case, SRFI 248 adds the ability for
execution of arbitrary code to the handler mechanism, so that
‘dynamic-wind’ can be disposed of in principle, and we are back to the
situation that only one fundamental feature is needed.
If one allows oneself to be less conservative and more innovative and
wants to get rid of these problematic uses of ‘dynamic-wind‘, the
model of SRFI 248 has to be changed from basically one handler/effect
type to several independent handler/effect types. (Such a model can be
built on top of SRFI 248.) SRFI 226 describes such a model. As SRFI
226 does not get rid of the legacy stuff, it is far from being minimal
and brief.
If Scheme were designed from scratch, allowing it to become the
language it is supposed/wants to be, there would probably be no
‘call/cc’ nor ’dynamic-wind’, but only ‘raise-continuable’ and a
procedure that installs a handler for a particular condition type (or
something equivalent in expressiveness):
(with-handler-for RTD HANDLER THUNK)
Here, the HANDLER will be called with the condition object and the
delimited continuation whenever an object in THUNK is raised that is
of the record type described by the record type descriptor RTD.
The ‘make-coroutine-generator’ example of SRFI 248 would become
(define make-coroutine-generator
(lambda (proc)
(define-condition-type &yield &condition
make-yield-condition yield-condition?
(value condition-value))
(define yield
(lambda (val)
(raise-continuable (make-yield-condition val))))
(define thunk
(lambda ()
(with-handler-for &yield
(lambda (c k)
(set! thunk k)
(condition-value c))
(lambda ()
(proc yield)
(eof-object)))))
(lambda ()
(thunk))))
The semantic difference would be that no other code could interfere
with the coroutine generator, as the condition type ‘&yield’ is
private.
This all is likely The Right Thing, but would need that the Scheme
community is willing to go back to the time (before around 1990) when
Scheme was still a dynamic language in the sense that
backwards-compatibility was less important than getting things right
(see, for example,
https://people.csail.mit.edu/jaffer/r3rs_10.html#SEC73 for the list of
changes from R2RS to R3RS).
It would also allow interpreting ‘set!’ as an effect like any
user-defined effect (as it should be).
Am Fr., 2. Jan. 2026 um 09:49 Uhr schrieb Marc Nieper-Wißkirchen
<xxxxxx@gmail.com>:
>
> PS I found Oleg's explanation of why a primitive ‘dynamic-wind’ should
> have no role in a language with delimited continuations:
> https://okmij.org/ftp/continuations/implementations.html#dynamic-wind
>
> Am Do., 1. Jan. 2026 um 13:48 Uhr schrieb Marc Nieper-Wißkirchen
> <xxxxxx@gmail.com>:
> >
> > Hi!
> >
> > Thanks for the question.
> >
> > The model of SRFI 248 (which is deliberately simple and basic but rich
> > enough to build more complex abstractions on top of it) is that there
> > is basically just one type of effect. Whatever effect is raised, the
> > innermost handler is called (and can move control to the next
> > enclosing handler by reraising the effect), so one can detect every
> > unwinding of the stack through
> > ‘with-unwind-handler’/‘raise-continuable’ and thus implement a version
> > of ‘dynamic-wind’ that works for delimited continuations.
> >
> > With delimited continuations, ‘call/cc’ is not really necessary any
> > more (except for backward compatibility). As the unwinding occurring
> > from instantiating a continuation K captured by ‘call/cc´ does not
> > trigger any unwind handler, one still needs the legacy ‘dynamic/wind’
> > as long as the legacy ‘call/cc’ exists. One could amend SRFI 248 by
> > integrating ‘call/cc’ fully by demanding that instantiating K raises a
> > condition object, which leads to triggering the unwind handlers. This
> > is less conservative but probably The Right Thing.
> >
> > Marc
> >
> > Am Do., 1. Jan. 2026 um 04:24 Uhr schrieb Eleanor Bartle
> > <xxxxxx@eleanor-nb.com>:
> > >
> > > Apologies for the noise. I’m a passive nerd, attempting to understand Scheme internals, enamoured by delimited continuations.
> > >
> > > One thing I don’t understand in this SRFI is how it would be able to dispense with dynamic-wind, were it not for call/cc. How does that come about? More precisely, why does the unwinding/rewinding of a delimited continuation not necessitate dynamic-wind, and why does that reason not apply to call/cc?
> > >
> > > Eleanor