在阅读了Eric Lippert 的回答后,我的印象是await
和call/cc
几乎是同一枚硬币的两个方面,最多有句法上的差异。然而,在尝试call/cc
在 C# 5 中实际实现时,我遇到了一个问题:要么我误解了 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
至关重要的是,当调用 continuation 时,程序状态会与调用历史记录一起恢复,从而foo
返回到main
并且永远不会返回到bar
。
但是,如果await
在 C# 中实现,则调用延续不会恢复此调用历史记录。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”永远不会被调用,这与 true-call/cc 示例不同,这是喜欢 C# 并赞扬其设计的另一个原因!