假设我有以下代码(使用类C语法):
void foo(int arg) { ... } int bar() { ... // call with continuation ... } foo ( bar() ) // after foo invocation
1)函数foo
调用函数bar
,它一直运行,直到到达call with continuation
的行。
2)在此行创建continuation
函数。它代表bar
和foo
的其余部分。 continuation
函数作为参数传递给call with continuation
函数。
3)call with continuation
函数对参数做任何想做的事情(例如它可能只存储在一个全局变量中)并返回。
4)call with continuation
返回后,我们立即跳转到“foo调用后”行,其余的bar
和foo
都没有执行。
5)为了继续执行bar
和foo
,我们应该显式调用continuation
函数(在(2)中创建并可能存储在(3)中)。一旦调用了continuation
函数,就会在call with continuation
之后立即执行。
这是对的吗?我错过了关于无限延续的事情吗?
答案 0 :(得分:4)
没有。通常,当您调用call/cc
时,无限制的延续(例如,使用Scheme的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
执行开始。我们输入bar
(我们尚未输入foo
;当我们完成bar
时,我们会这样做。
当我们在call/cc
中点击bar
时,“程序上下文”会变成一个称为延续的对象。此时,程序上下文包括“完成执行bar
,然后对结果调用foo
,然后执行foo
调用之后的任何操作”。继续传递给作为call/cc
的参数给出的函数,在我上面的示例中为handler
。
handler
对延续做了一些事情。我们假设它将它存储在全局变量中。然后它会在call/cc
调用后立即返回到bar
内部。
让我们说我们在这一点上打印出来的东西。然后bar
结束,我们致电foo
,然后结束。
如果我们现在在savedk
中应用延续,控制会跳回bar
并将程序上下文恢复为“完成执行bar
”,然后调用foo
在结果上,然后在foo
调用之后执行任何操作。所以我们打印另一条线。实际上,如果我们不清除savedk
变量或测试其他状态,如果“在foo
调用后执行任何操作”再次调用savedk
,我们可能会得到一个无限循环!