5 ms·
It says it's just setjmp/longjmp, but later on expands on that, saying you can jump not only up the stack, but down and sideways too (#1). I think the best exp
by csl 11y ago
It says it's just setjmp/longjmp, but later on expands on that, saying you can jump not only up the stack, but down and sideways too (#1).
I think the best explanation (mentioned in the article) is that you take a copy of the entire call stack, and can then reinstate it whenever you want to.
An even simpler explanation is Guy L. Steele's that it's "gotos with parameters", that is, basically goto, but let's you pass a parameter to the destination:
(define saved-continuation #f)
(display (string-append "hello "
(call/cc (lambda (here)
(set! saved-continuation here)
"world"))
"!\n"))
; Displays: "hello world!"
(saved-continuation "everyone")
; Displays "hello everyone!"
Running it with guile:
$ guile cc.scm
hello world!
hello everyone!
This code makes `saved-continuation` equivalent to
(lambda (param)
(display (string-append "hello " param "!\n"))))
Matt Might has an explanation, too: http://matt.might.net/articles/programming-with-continuations--exceptions-backtracking-search-threads-generators-coroutines/ http://matt.might.net/articles/programming-with-continuation...
Finally, we have delimited continuations, which lets you basically slice off a portion of the current call stack, instead of taking it in its entirety. It's more powerful and lets one create true functions, and implement any other control flow construct.
#1: What's often not mentioned is the fact that you can only jump to code you've already run. So you can't jump straight into somewhere your program has not been, yet.
- agumonkey 11y agoI was blinded by the continuation thing for a while, I loved the functional interface of it and the applications. But more than a GOTO or a JMP, they do represent a chunk of an evaluation process. It's easier to see with delimited continuations though and feels quite different than GOTOs. Or, to be honest, maybe that the late 90s view of GOTOs, maybe people in the 60s did use them as clean call between functional steps expressed as States in a State Machine, and not the spaghetti soup of easy monkeypatch you can see sometimes.
- iso8859-1 11y agoYou can't reinstate the stack after restarting the process, either. Which would be nice, for saving state in a cross-platform way (not using core dumps).
- csl 11y agoNot by default, but I've seen some schemes offer serialization of continuations, for example http://wiki.call-cc.org/eggref/4/suspension http://wiki.call-cc.org/eggref/4/suspension
- jpolitz 11y agoFor an approach that does this, check out how Racket's web server manages statelessness across requests: http://docs.racket-lang.org/web-server/stateless.html#%28part._considerations%29 http://docs.racket-lang.org/web-server/stateless.html#%28par... http://cs.brown.edu/~sk/Publications/Papers/Published/pcmkf-cont-from-gen-stack-insp/paper.pdf http://cs.brown.edu/~sk/Publications/Papers/Published/pcmkf-...
- iso8859-1 11y agoThat paper is great, thanks! Can you recommend any recent papers regarding this subject? That paper was from ICFP '05.
- jpolitz 11y agoOff the top of my head, I'm not sure (other than follow-up work to this paper, like http://jeapostrophe.github.io/home/static/icfp065-mccarthy.pdf http://jeapostrophe.github.io/home/static/icfp065-mccarthy.p... [ICFP '09]). But, the ideas in that paper aren‘t any less true just because they are from 2005, and they are still what the Racket web server runs on as far as I know :-)
- ArkyBeagle 11y agoIt seems the calls in ucontext.h for *nix ( and the corresponding equivalents in Windows ) might be an improvement over setjmp/longjmp. Emphasis "might be" - details not in evidence, all that. I might remember wrong, but I recall setjmp/longjmp having constraints on when they're useable - your "up, down sideways..." And given that, perhaps pthreads are more civilized.
- maxiepoo 11y agoI expected that code to print "hello everyone!" forever but apparently the top level acts as a delimiter. This is why I think delimited continuations make more sense since even call/cc is already "delimited" but with no concept for it. A version that would print forever: (let ((_ (display ...))) (saved-continuation "everyone"))
- csl 11y agoExactly! The top-level is actually special in many circumstances. Some people have suggested removing call/cc from Scheme. I don't know if they want to put delimited continuations in its stead. See http://okmij.org/ftp/continuations/against-callcc.html http://okmij.org/ftp/continuations/against-callcc.html