После прочтения ответа Эрика Липперта у меня сложилось впечатление, что 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
Важно, что при вызове продолжения восстанавливается состояние программы вместе с историей вызовов , так что 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 # и хвалить его дизайн!