Am Sa., 29. Okt. 2022 um 15:49 Uhr schrieb Marc Nieper-Wißkirchen <xxxxxx@gmail.com>: > > Am Sa., 29. Okt. 2022 um 14:49 Uhr schrieb Marc Feeley > <xxxxxx@iro.umontreal.ca>: > > > > > On Oct 29, 2022, at 4:13 AM, Marc Nieper-Wißkirchen <xxxxxx@gmail.com> wrote: > > > > > > Am Sa., 29. Okt. 2022 um 04:54 Uhr schrieb Marc Feeley > > > <xxxxxx@iro.umontreal.ca>: > > >> > > >>> On Oct 27, 2022, at 2:01 AM, Marc Nieper-Wißkirchen <xxxxxx@gmail.com> 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.