Continuations by example: Exceptions, time-traveling search, threads, and more
matt.might.netI always start Matt Might articles thinking "Okay, THIS is the one I'm going to understand all the way to the very end without unlearning what I just read, else I die," and alas, I have again died.
I'm having an ADHD night and I had the same thought, except I haven't died yet. Felt like giving up three times already, but I did have a click moment after playing around with a scheme repl for a couple of minutes. I understand the first example of call/cc now!
Edit: Tried playing around with mit-scheme, but it doesn't work with the ctrl-v'ing the examples. Chezscheme does work.(display (call/cc (lambda (cc) (display "I got here.\n") (cc "This string was passed to the continuation.\n") (display "But not here.\n"))))It seems that MIT-Scheme needs the cc function to be a function of 1 argument (the return value for the continuation)[0]
Changing it to the following should work:
[0] https://www.gnu.org/software/mit-scheme/documentation/stable...(let ((start #f)) (if (not start) (call/cc (lambda (cc) (set! start cc)))) (display "Going to invoke (start)\n") (start #f))For what it's worth, almost any time Matt writes about Scheme he's likely using Racket so it'd be worth trying that for his posts!
Me to. Level failed, but then i found this cheat code from apache and at lest i now understand basics.
AFAIK Javaflow's been inactive for over a decade. Newer implementations for the same concept include https://github.com/offbynull/coroutines and https://github.com/vsilaev/tascalate-javaflow/.
Full disclosure: I'm the one who built / owns the first project.
On the topic of inactive continuation implementations for Java: I implemented native support for both delimited (shift/reset) and non-delimited (call/cc) continuations in the Avian JVM. See https://github.com/ReadyTalk/avian/blob/master/test/extra/Co... for some mind-bending examples.
Love it. Lmk if you never need a hand. I was on the core analysis team at Fortify.
Thanks for sharing this background and cool project.
I was actually relieved when I found this article [1] which argues against call/cc as a core language feature. Alas, I think the argument does not dismiss _delimited continuations_, so now my burden has shifted from mastering call/cc to mastering shift/reset :-/ [2].
I think I've found a good use for continuations in a parser combinator library I'm writing, though I haven't gotten around to working on the corresponding feature yet.
Has anyone used continuations in a serious/non-academic way?
I used to implement an equivalent of exit or return statement, like in this example.
There are more idiomatic and easy ways to write this, but when you have to many nested and not nested for's, sometimes it is useful to have a magical exit-everything-now.#lang racket ; implement sqrt in a very inefficient way (let/ec exit (for ([i 10]) (when (= (* i i) 49) (exit i))) "not found :(") ;==> 7Continuations can be implicitly used. If you have a language that is compiled using transformation to CPS. Then continuations are everywhere under the hood.
You could dispute "serious", but I've used it in a not!lisp for various control flow purposes.
func a0 a1 = callcc \return: # ... callcc (again =) # ... x ?? return y again again
Wow, imagine writing in such an unreadable language