Greg Hendersott isn’t a typical hacker. He’s the creator of Cakewalk, a digital audio workstation that ruled the Windows roost for about 20 years. Hendershott is the John Carmack of music creation software.
A continuation is best understood by trying to implement an evaluator that can pause.
An evaluator is just a function that takes in some JSON and spits out a result. [if [> 2 1] 8 9] would produce 8.
Say you wanted to pause during the evaluation of the [> 2 1] condition. What do you do? How would you resume it later? Well, you have the original JSON. Meaning you have the whole program code. You know where you are in that program code. And you know the current state of the program. So you save those somewhere, return from your evaluator, then restore the values later and tell your evaluator to start from a specific location.
One non intuitive aspect of this, though, is that “the current values of your program” includes “what the evaluator should do at each step”. Imagine evaluating [if [> 2 1] 8 9]. In your eval function, you check “if the first thing in the list is “‘if’”, call the ‘eval-if’ subroutine.” Your two options here are to either (a) have eval-if evaluate the condition and then return the result, or (b) pass the condition and both branches to the function, and have that function evaluate the condition and one of the branches.
The latter form is called continuation passing, and it’s much easier to pause and resume. But you’re restricted to tail calls only. You can do it the other way by saving a stack.
Thank you. I think there is more in it, though. When you only talk about ability to pause, you still don't change the sequence of execution - you only can inspect it at arbitrary moments. The sequence itself remains immutable. It's not so clear when you use continuations themselves within that sequence. Say, you save current continuation as an object in memory and then return to it - not immediately but after some other actions are done. In this case you have more questions about how perfect is your return to the state when that continuation was saved is. Indeed a perfect return would mean the whole memory state of the machine is restored exactly as it was when the continuation was taken, and, barring side effects, the execution will repeat what was done after the continuation was taken but before it was returned to.
I'd like to hear more about control flow state and data flow state here.
https://news.ycombinator.com/item?id=7601506
https://news.ycombinator.com/item?id=9692499