看完Eric Lippert的回答后,我觉得await
和call/cc
基本上是同一个硬币的两面,最多只有语法上的区别。然而,在尝试在C# 5中实现call/cc
时,我遇到了一个问题:要么我误解了call/cc
(这很可能),要么await
仅仅是回忆起call/cc
。
考虑以下伪代码:
function main:
foo();
print "Done"
function foo:
var result = call/cc(bar);
print "Result: " + result;
function bar(continuation):
print "Before"
continuation("stuff");
print "After"
如果我对call/cc的理解正确,那么这应该会打印:
Before
Result: stuff
Done
关键是,当调用续体时,程序状态将被恢复 连同调用历史记录,以便 foo
返回到 main
并且不会回到 bar
。然而,如果使用 C# 中的
await
来实现,调用续体不会恢复这个调用历史记录。 foo
返回到 bar
,我无法看到任何方法可以使用 await
使正确的调用历史记录成为续体的一部分。请解释:我是否完全误解了
call/cc
的操作,还是说 await
只是与 call/cc
不太相同?
现在我知道答案后,必须说有很好的理由认为它们是相当相似的。想象一下上面的程序在伪 C#-5 中的样子。
function main:
foo();
print "Done"
async function foo:
var result = await(bar);
print "Result: " + result;
async function bar():
print "Before"
return "stuff";
print "After"
因此,虽然C# 5风格从未给我们提供传递值的续延对象,但总体相似性非常惊人。除了这一次完全明显的是,“After”永远不会被调用,不像在真正的call/cc示例中那样,这是喜爱C#并赞扬其设计的另一个原因!