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.
