Am Sa., 29. Okt. 2022 um 15:49 Uhr schrieb Marc Nieper-Wißkirchen
<[email protected]>:
>
> Am Sa., 29. Okt. 2022 um 14:49 Uhr schrieb Marc Feeley
> <[email protected]>:
> >
> > > On Oct 29, 2022, at 4:13 AM, Marc Nieper-Wißkirchen 
> > > <[email protected]> wrote:
> > >
> > > Am Sa., 29. Okt. 2022 um 04:54 Uhr schrieb Marc Feeley
> > > <[email protected]>:
> > >>
> > >>> On Oct 27, 2022, at 2:01 AM, Marc Nieper-Wißkirchen 
> > >>> <[email protected]> wrote:
> > >>>
> > >>> I am also still hoping for a reply from Marc in the discussion about
> > >>> "weak threads".
> > >>>
> > >>> [...]
> > >>
> > >> Sorry for not getting back sooner.  I have continued my reading of the 
> > >> SRFI 226 spec.  Unfortunately my time is still constrained and the spec 
> > >> is huge so my comments are bound to be more superficial than I’d like.  
> > >> Here's what stands out.
> > >
> > > There's no need to apologize. I am very grateful to all that take the
> > > time to read and think about the specification.
> > >
> > >> (call-in-continuation cont thunk) misses an opportunity of having the 
> > >> more general form (call-in-continuation cont proc arg1...) so that it 
> > >> can be called with a procedure and as many arguments as needed.  Instead 
> > >> of (call-in-continuation k (lambda () (values tmp ...)) you could write 
> > >> (call-in-continuation k values tmp ...).  See the definition of the 
> > >> continuation-graft form that you cite:
> > >
> > > I will generalize call-in-continuation in this respect.  Thank you for
> > > the suggestion.
> > >
> > > [...]
> > >
> >
> > Let me also suggest a name change (for a shorter name) and giving a name to 
> > the “return” operation:
> >
> >   (call-in k proc arg1...)
> >   (return-to k val1...)        equivalent to (call-in k values val1...)
> >
> > These are the continuation-graft and continuation-return procedures of the 
> > “better API” paper, but with more palatable names.  It reads well to write:
> >
> >   (define (inverse lst)
> >     (call/cc
> >       (lambda (caller)  ;; caller is a continuation object
> >         (map (lambda (x)
> >                (if (= x 0)
> >                    (return-to caller 'error)
> >                    (/ 1 x)))
> >              lst))))
> >
> > >> Note also that one of the main points of the "Better API" paper is to 
> > >> treat continuations as a specific type different from procedures so that 
> > >> the burden of the procedure representation can be avoided (conceptual 
> > >> and also run-time cost for creating the procedure), and also have other 
> > >> operations such as (continuation? obj), (continuation-length k), etc.  I 
> > >> view "continuations as procedures" to be a historical blunder that was 
> > >> motivated by CPS style.  If you have ever tried to explain how call/cc 
> > >> works to students you will probably understand what I'm talking about: 
> > >> "call/cc receives a procedure and calls this procedure with a procedure 
> > >> that represents the continuation".  Too many procedures for most 
> > >> students.  With SRFI 226 there's an opportunity to correct this by 
> > >> making (call-with-non-composable-continuation proc) call proc with a 
> > >> continuation object that is separate from procedures.  It changes very 
> > >> little to the API, except that those continuations have to be called 
> > >> with (call-in-continuation k values ...) or some new more specific 
> > >> procedure (return-to-continuation k ...).
> > >
> > > From a theoretical point of view, I agree with you, and I also see the
> > > point of teaching.  For historical reasons (call/cc), however, I would
> > > like to leave the API as is. Given the presence of call/cc and
> > > existing code, I feel that introducing a new, theoretically more
> > > appealing approach while the historical one is still there leads to
> > > its own share of problems and confusion.
> > >
> > > If you want, you can view a continuation (as created by call/cc) as an
> > > element of a new abstract datatype, which, however, happens to be
> > > callable.  To enforce this point of view, SRFI 226 has introduced the
> > > procedure `continuation?`, which checks for whether an object is a
> > > continuation.
> >
> > As I say this conflation of the procedure and continuation concept hurts
> >
> > 1) understanding: not just explaining to students, but also this 
> > exceptional thing that in (+ 1 (k …)) the addition is never executed yet (k 
> > …) is a procedure call (I know it would still be a possibility to have a 
> > procedure behave like this, but typically for a continuation there would be 
> > a visual marker that warns of something exceptional happening: (+ 1 
> > (return-to k …)) ).
>
> We could mitigate this by stopping calling our continuations just "k".
> I.e., write "return-to-k", so you get more or less the equivalent of
> the latter expression.
>
> > 2) performance: the underlying continuation structure needs to be wrapped 
> > in a closure that needs to be created (more memory allocation), and a 
> > procedure call is needed to restore a continuation (whereas call-in and 
> > return-to could be inlined by the compiler and optimally pass the arguments 
> > to it).
>
> The underlying continuation structure can be the closure, so more
> memory allocation is not necessary. Inlining would also remain the
> same: Either the compiler can infer the type of the continuation
> expression, in which inlining can happen, or it cannot, in which case
> a dynamic type check has to be made in both implementation models.
>
> > Certainly the “continuation as procedure” API for call/cc must stay the 
> > same for compatibility, but all the new continuation operations in SRFI 226 
> > could be using a separate type.
> >
> > To bridge the two points of view, instead of (continuation? obj) you could 
> > have (procedure->continuation proc) that extracts the continuation object 
> > of proc if it is a “continuation as procedure” created by call/cc and 
> > returns #f otherwise.  Moreover, all the continuation procedures defined by 
> > the SRFI could accept both a continuation object and a “continuation as 
> > procedure”.  In other words it would not be a requirement to represent 
> > continuations as procedures, except for call/cc for historical reasons.
> >
> > Alternatively, a variant of call/cc, perhaps called 
> > with-current-continuation, would use continuation ojects but would be 
> > otherwise equivalent.  call/cc could then be defined as:
> >
> >   (define (call/cc receiver)
> >     (with-current-continuation
> >      (lambda (cont)  ;; cont is a continuation object
> >        (receiver (lambda vals (apply return-to cont values vals))))))
> >
> > This may be the last chance to get the, as you say, “theoretically more 
> > appealing approach” while preserving the API of call/cc for historical 
> > reasons.
>
> I would like to hear from more Schemers about this idea because it is
> a radical change from how continuation objects have been presented so
> far.
>
> It should also be noted that composable continuations behave like
> procedures, in particular, they return. Something like "return-to" for
> composable continuations wouldn't make sense.  So we would see a split
> between non-composable and composable continuations.  Maybe this is
> good.
>
> Another approach would be to leave everything as is (including the
> continuation? predicate) but to add "return-to" and
> "continuation->procedure" and abbreviate call-in-continuation to
> "call-in".  This way, the old interface would still be supported while
> there would be a canonical way to write code following the principles
> from your paper.

Added "call-in" and "return-to".  It's in the latest version in my
personal repo.

Reply via email to