4 ms·
A common strategy for implementing compilers for continuation-enabled languages is transforming code into "continuation-passing style" (CPS). That means, basic
by mbrock 9y ago
A common strategy for implementing compilers for continuation-enabled languages is transforming code into "continuation-passing style" (CPS).
That means, basically, converting it into total "callback hell", so that functions don't return, they just call other functions with callbacks.
(There's a special "exit" callback that is implicitly the callback for the main function.)
Some imagination is required to see how, say, a for loop is rendered into CPS, but if you first imagine turning the loop into functional programming then it's easier (like in JavaScript, if you want to wait for an asynchronous thing in your for loop body, you have to basically do a CPS transformation manually, or use async/await which is closely related).
So basically in Scheme, your code is always in a callback-passing style, just that the language cleverly hides it, and then lets you explicitly access the current callback (using call/cc).
If you have experience with async programming in JavaScript, it should make sense that this lets you easily implement things like concurrency, custom blocking operations, etc.
Just like how JavaScript callbacks can be called several times, so with continuations. Since the callbacks are implicit in Scheme, you can make what appears to be a function that returns several times ("nondeterminism").
Callbacks can of course take several arguments. Most languages have an asymmetry where functions have several parameters but can only return one value. With continuations, it's easy to imagine calling them with several arguments. So in a language with continuations, it makes sense to have multiple return values too.
- tonyg 9y agoThis is one of the reasons why having an implementation that correctly handles tail calls is so important.