Suppose, I have the following code (in C-like syntax):
void foo(int arg) { ... } int bar() { ... // call with continuation ... } foo ( bar() ) // after foo invocation
1) Function foo
invokes function bar
, which is running until it reaches the line with call with continuation
.
2) At this line a continuation
function is created. It represents the rest of bar
and foo
. The continuation
function is passed as an argument to call with continuation
function.
3) The call with continuation
function does whatever it wants with the argument (eg it may just store in a global variable) and returns.
4) Once the call with continuation
returns we immediately jump to the line with "after foo invocation" and the rest of bar
and foo
are not executed.
5) In order to continue execution of bar
and foo
we should explicitly invoke the continuation
function (created in (2) and probably stored in (3)). Once the continuation
function is invoked the execution continues immediately after the call with continuation
.
Is it correct? Am I missing something about undelimited continuations?
No. Typically, undelimited continuations (eg created with Scheme's call/cc
) jump when you invoke the continuation
, not when you call call/cc
(aka call-with-current-continuation
).
So, fleshing out your example:
continuation savedk;
void foo(int arg) { ... }
int bar() {
...
call/cc(handler)
// after call/cc
println "after call/cc"
...
}
void handler(continuation k) {
savedk = k
}
foo ( bar() )
// after foo invocation
Execution starts. We enter bar
(we haven't entered foo
yet; we'll do that when we get done with bar
).
When we hit the call to call/cc
in bar
, the "program context" is turned into an object called a continuation. At this point, the program context consists of "finish executing bar
, then call foo
on the result, and then do whatever comes after the foo
invocation". The continuation is passed to the function given as an argument to call/cc
, which is handler
in my example above.
handler
does something with the continuation. Let's assume it stores it in a global variable. Then it returns to the point right after the call/cc
call, still inside of bar
.
Let's say we print something out at this point. Then bar
finishes and we call foo
, and it finishes.
If we now apply the continuation in savedk
, control jumps back into bar
and restores the program context to "finish executing bar
, then call foo
on the result, and then do whatever comes after the foo
invocation". So we get another line printed. In fact, if we don't clear the savedk
variable or test some other state, we might get an infinite loop if "do whatever comes after the foo
invocation" is call savedk
again!
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.