简体   繁体   中英

Understanding undelimited continuations

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
  1. Execution starts. We enter bar (we haven't entered foo yet; we'll do that when we get done with bar ).

  2. 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.

  3. 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 .

  4. Let's say we print something out at this point. Then bar finishes and we call foo , and it finishes.

  5. 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM