了解无定界延续

Mic*_*ael 3 language-agnostic continuations programming-languages functional-programming

假设,我有以下代码(类似 C 的语法):

void foo(int arg) { ... }

内部酒吧(){
...
// 继续调用 
...
}

foo ( bar() )
// 在 foo 调用之后

1) 函数foo调用 function bar,该函数一直运行直到到达带有 的行call with continuation

2) 在这一行continuation创建了一个函数。它代表的休息barfoo。该continuation函数作为参数传递给call with continuation函数。

3)call with continuation函数对参数做任何它想做的事情(例如,它可能只存储在一个全局变量中)并返回。

4) 一旦call with continuation返回,我们立即跳转到带有“after foo invocation”的那一行,其余的barfoo不执行。

5)为了继续执行bar,并foo应明确地调用continuation函数(在(2创建),可能存储在(3))。一旦continuation调用该函数,则在 之后立即继续执行call with continuation

这是正确的吗?我是否遗漏了有关无分隔延续的内容?

Rya*_*per 5

不。通常,未定界的延续(例如,用 Scheme 的 创建call/cc)在您调用 时跳转continuation,而不是在您调用call/cc(又名call-with-current-continuation)时。

所以,充实你的例子:

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
Run Code Online (Sandbox Code Playgroud)
  1. 执行开始。我们输入bar(我们还没有输入foo;我们会在完成后输入bar)。

  2. 当我们调用call/ccin 时bar,“程序上下文”变成了一个称为延续的对象。此时,程序上下文包括“完成执行bar,然后调用foo结果,然后执行foo调用之后的任何操作”。延续被传递给作为参数给定的函数call/cc,这handler在我上面的例子中。

  3. handler对延续做了一些事情。让我们假设它将它存储在一个全局变量中。然后它在call/cc调用后立即返回到该点,仍然在bar.

  4. 假设我们此时打印了一些东西。然后bar完成,我们调用foo,它就完成了。

  5. 如果我们现在应用 in 中的延续savedk,控制会跳回bar并恢复程序上下文以“完成执行bar,然后调用foo结果,然后执行foo调用之后的任何操作”。所以我们打印了另一行。事实上,如果我们不清除savedk变量或测试其他状态,如果再次foo调用“调用后执行任何操作”,我们可能会遇到无限循环savedk