Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
SRFI 226: Control Features (schemers.org)
25 points by bshanks on Dec 11, 2022 | hide | past | favorite | 6 comments


I read this after perusing the linked resources last time it surfaced, and although I'm no expert, I really like this solution. I'd love to hear from the Scheme implimentors and macro-writers who have actually used call/cc. The control offered over the scope of a continuation, reminding me (model-wise) of a patchset cherry-picked off the head of a git branch, appesrs to soundly address preformance concerns, while the ability to return a value to the continuation's call-site looks like a huge advantage.


> return a value

oops; by which I mean the flexibility, eg. with helpers like call-in and return-to.


"Finally, a primitive (call-in-continuation) is provided that allows calling a procedure in a given continuation instead of just delivering values to it."

can anyone add some language about what this is? I read this and the section on it, and remain deeply confused


I can try!

> (call-in-continuation cont proc obj …)

First, just some context, to be sure I've got my facts straight:

'call/cc' allows you to capture the continuation which invokes it. That continuation is represented as a procedure passed into a unary function. That function usually uses 'set!' to export the continuation into a broader scope before returning an initial value to call/cc's caller. Later, invoking that continuation with a value tosses your current continuation and returns you to the call-site of call/cc, where the call/cc form now returns to it's caller again but with the provided value.

In contrast, 'call-in-continuation' takes a procedure and some arguments. It tosses the current continuation, returning to the call-site of call/cc, but then instead of returning a supplied value directly to call/cc's caller, it returns the result of evaluating the given procedure (applying it to any other supplied arguments) here at the call/cc call-site.

Supplied arguments are evaluated before returning to the continuation, just like when invoking the continuation itself with some values.

Mirroring the example from Guile's docs[1]:

  (define kont #f)
  (let ((x 1))
    (format #t "the return is ~a\n"
            (call/cc (lambda (k)
                       (set! kont k)
                       (1+ x)))))
  ⇒ the return is 2
  
  (kont 3)
  ⇒ the return is 3
  
  (kont (+ x 3))
  ⇒ Unbound variable: x
  
  (kont (lambda () (+ x 3))
  ⇒ the return is #<procedure 1d823a8 at <unknown port>:5:6 ()>
  
  (call-in-continuation kont (lambda () (+ x 3)))
  ⇒ the return is 4
  
  (call-in-continuation kont (lambda (y) (+ x y)) 4)
  ⇒ the return is 5

[1]: https://www.gnu.org/software/guile/manual/html_node/Continua...


Oh, and a note on why you'd want this: while you may be able to construct a superficially similar example by expecting call/cc to return a thunk and evaluating it at the call-site, you can't always control the call-site and might be using one continuation in multiple contexts.

The try/catch implementation on page two of A Better API for First Class Continuations show-cases a specific use-case (albeit in the form of continuation-graft), though I'm still staring at it and trying to figure out if a few more parens and thunks wouldn't do the trick (more verbosely) in that context.


Finally, promises as defined in this specification can deliver multiple values when forced, an extension too natural to ignore

Oh yes, excellent, looking forward to playing around with multiple-value lazy streams (srfi-41).




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: