【发布时间】:2012-04-07 06:22:16
【问题描述】:
阅读Eric Lippert’s answer 后,我的印象是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
至关重要的是,当调用 continuation 时,程序状态会随着调用历史恢复,因此 foo 返回到 main 并且永远不会返回到 bar。 p>
但是,如果在 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”永远不会被调用,不像在 true-call/cc 示例中,这是喜欢 C# 并赞扬其设计的另一个原因!
【问题讨论】:
-
Timwi 是正确的; await 更像是一个“本地效果”调用/cc;这是我最初的答案中没有想到的一个微妙之处。我已经更新了。
标签: c# continuation