4 ms·
The with-baffle is interesting (and call-with-exit). My personal take on Scheme is that call/cc is elegant and powerful in the same way that assembly language
by klodolph 6y ago
The with-baffle is interesting (and call-with-exit).
My personal take on Scheme is that call/cc is elegant and powerful in the same way that assembly language is elegant and powerful—and just like it’s hard to reason about programs that make creative use of assembly language constructs, it’s hard to reason about programs that make creative use of call/cc. Just like you can implement nearly any control structure in assembly, you can implement many with call/cc. I was once working on a Scheme compiler but abandoned the efforts once I realized the enormous negative impact that call/cc has on writing compilers, interpreters, and library code.
Do you want to write a reasonably fast and general mapcar? Do you want to do some basic escape analysis to see if you can allocate a value on the stack? Better have a good, long think about things. The withering gaze of call/cc will make your face melt.
So, years ago, I was hopeful that there would be an officially sanctioned Scheme without call/cc. Call it what you will. It never materialized.
You can think of it as two sides of the same coin—just like objects are a poor substitute for closures and closures are a poor substitute for objects, call/cc is a poor substitute for exception handling, and exception handling is a poor substitute for call/cc. R7RS adds SRFI-34, but you still see stuff like with-baffle and call-with-exit precisely because call/cc is like a stick of dynamite that you can put in your code, and there’s no way it can work across any kind of FFI boundary without severe restrictions.
- StefanKarpinski 6y agoGood point — especially since as opposed to full continuations, which are essentially impossible to implement efficiently, coroutines / one-shot continuations, have a completely obvious and intuitive implementation: each coroutine is a separate stack and when one coroutine yields to another, it's just a jump to executing code on a different stack.
- samatman 6y agoAnd with coroutines, it's frequently possible to implement a "multi-shot" continuation, by cloning any mutable parameters, and returning a generator which returns a fresh coroutine each time its called. It's not the same thing as a delimited continuation (is it?) but it's close enough for my purposes. Normally, you just want functions, but sometimes, you want coroutines. Normally, one-shot coroutines are fine, but sometimes you want multi-shot. I have never once felt like a full-blown continuation was the construct I was missing.
- bigbubba 6y agoFrom what I've read and heard, call/cc is generally considered strictly inferior to delimited continuations.
- the-smug-one 6y ago> I was once working on a Scheme compiler but abandoned the efforts once I realized the enormous negative impact that call/cc has on writing compilers, interpreters, and library code. Isn't implementing call/cc trivial if you have CPS? The other criticisms are common and valid. Racket uses delimited continuations instead because of the pitfalls of call/cc.
- klodolph 6y ago> Isn't implementing call/cc trivial if you have CPS? You’re right that call/cc itself can be trivial. The problem is that everything else becomes way more complicated because call/cc exists. The critical thing to remember is that if you have call/cc, ANY user-supplied function can return multiple times. In general people expect library functions to “just deal with it” and in practice that means that (1) half your library functions might just be broken but you don’t know it because they fail some weird test case involving call/cc that you didn’t cover (1) you can’t do anything clever to speed up your library functions and (2) your compiler won’t be capable of doing the escape analysis to fix the performance issues in your library functions. The thing is, you can conceptualize of call/cc as being just “free” if you think of the language as a way to program a continuation-passing machine, but when you do that, you’re basically one step away from some weird garbage-collected assembly language with unlimited goto. In order to reason about programs more effectively we largely abandoned goto except for the few cases where it’s the right tool. Most of the time we like our control structures to match the stack—you go IN to a function exactly once, and then OUT of the function exactly once.
- Zickzack 6y agoScheme is properly tail recursive. That means that CPS conversion is going to work. Seen that way, call/cc is just a convenience feature that spares you the work of the conversion. Introducing weaker language constructs and claiming that they are easier to reason about seems spurious, because there still may be full fledged continuations coming with CPS. I guess this so called reasoning will only work for a limited subset of all programs. I actually think that call/cc has the advantage of forcing people to realise what the ramifications of proper tail recursion are.
- bjoli 6y agoNobody likes call/cc except for the chicken scheme people where call/cc is more or less free. Delimited continuations is the bee's knees. They are faster, more easy to reason about, captures only what you tell them to (and thus are better in a GC language). Given enough time they will replace call/cc entirely. Buy, hey, don't take my word for it. I will appeal to authority and post this: http://okmij.org/ftp/continuations/against-callcc.html http://okmij.org/ftp/continuations/against-callcc.html
- bollu 6y agoWhat's a good language and textbook / lectures to pickup delimited continuations and how to use them?
- bjoli 6y agoI don't know really. I was introduced to them through Andy Wingo's blog wingolog.org and ported some call/cc benchmarks to use delimited continuations tomlearn howmto use them (and how they differ). Then I went head first into the source code of guile-fibers, a parallel concurrent ML implementation for guile that uses delimited continuations. It implements a full CML system as a library, which really is a testament to the power of delimited continuations. There is a lecture by Matthew Flatt held at Microsoft research about delimited continuations where he uses a web server to show the differences of delimited vs undelimited continuations somewhere in YouTube. Edit: btw the speed difference with regards to overhead between call/cc and call-with-prompt was something like an order of magnitude for simple things like generators and the rather well known fibcc benchmark.
- sparkie 6y agoThere's a nice collection of material here: https://github.com/rain-1/continuations-study-group/wiki/Reading-List https://github.com/rain-1/continuations-study-group/wiki/Rea...
- bitwize 6y agoI would rather see delimited continuations, but the Scheme community doesn't seem to have settled on a way to implement and represent them in the language. Nevertheless, having some form of continuation mechanism is more in line with Scheme being a small but powerful core upon which any programming construct can be built. Sure, most programmers out there would rather express things in terms of try/catch. But the idea is not to have continuations replace try/catch, but to have try/catch expressible in terms of continuations. Then it becomes a library you load and depend on, and theoretically runnable in any Scheme implementation that supports the continuation mechanism the try/catch library uses.
- bollu 6y agoWhat's a good language and textbook / lectures to pickup delimited continuations and how to use them?