- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
看完Eric Lippert’s answer我的印象是 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# 并赞扬其设计的原因!
最佳答案
await
确实和call/cc
不太一样。
您正在考虑的那种完全基础的 call/cc
确实必须保存和恢复整个调用堆栈。但是 await
只是一个编译时转换。它执行类似的操作,但不使用真实 调用堆栈。
假设您有一个包含 await 表达式的异步函数:
async Task<int> GetInt()
{
var intermediate = await DoSomething();
return calculation(intermediate);
}
现在假设您通过 await
自身 调用的函数包含一个 await
表达式:
async Task<int> DoSomething()
{
var important = await DoSomethingImportant();
return un(important);
}
现在想想当 DoSomethingImportant()
完成并且其结果可用时会发生什么。控制返回到 DoSomething()
。然后 DoSomething()
完成,然后会发生什么?控制返回到 GetInt()
。如果 GetInt()
在调用堆栈上,则行为与 完全相同。但事实并非如此;您必须在希望以这种方式模拟的每个 调用中使用await
。因此,调用堆栈被提升到在等待程序中实现的元调用堆栈。
顺便说一句,yield return
也是如此:
IEnumerable<int> GetInts()
{
foreach (var str in GetStrings())
yield return computation(str);
}
IEnumerable<string> GetStrings()
{
foreach (var stuff in GetStuffs())
yield return computation(stuff);
}
现在如果我调用 GetInts()
,我得到的是一个对象,它封装了 GetInts()
的当前执行状态(以便调用 MoveNext ()
在它停止的地方恢复操作)。此对象本身包含遍历 GetStrings()
并在 that 上调用 MoveNext()
的迭代器。因此,真正的 调用堆栈被对象层次结构所取代,这些对象层次结构每次都通过对下一个内部对象的 MoveNext()
的一系列调用来重新创建正确的调用堆栈。
关于C# 等待与延续 : not quite the same?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9826535/
可以说我只是使用 pygame 有一个正常的游戏循环。 run = True while run: for event in pygame.event.get(): if ev
如何让控制台应用程序运行直到用户输入“Q”、“q”、“Quit”或“quit”来终止它? 这是我当前的代码: public class Class1 { [STAThread] static
我正在创建一个基于 promise 的 API。如果我一次发出一个请求,一切都会正常,但是,如果 2 个或更多请求在一秒内到达服务器,我会收到以下错误 Error: Cannot enqueue Qu
考虑: (gdb) q A debugging session is active. Inferior 1 [process 9018] will be killed. Quit an
我有以下设置: int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); // Create the DBM
我的停靠菜单总是自动添加“退出”和其他 2 个菜单项,我如何阻止/修改它们? 更新: 确实没有办法删除/阻止/重定向“退出”菜单项。最后像打击一样使用了彼得的推荐希望对其他人有帮助 -(NSAppli
这是我的代码:1. 用户输入两个名称,中间有一个空格。这意味着需要读取两个字符串。 IE。输入: 约翰·多伊。 然后在字符数组中检查字符串。 (工作正常)。 while 循环一直持续到用户输入“sto
刚刚弄乱了 pygame 并遇到了这个错误。 代码: import sys import pygame pygame.init() size = width, height = 600, 400 sc
看完Eric Lippert’s answer我的印象是 await和 call/cc几乎是同一枚硬币的两面,最多只是句法上的差异。然而,在尝试实际实现时 call/cc在 C# 5 中,我遇到了一个
Memcached quit 命令用户关闭一个客户端连接 语法 quit 范例 连接到127.0.0.1 上 11211 的 Memcached 服务, 然后退出 $ telnet 12
这只是一种方便,但我认为很有用。请注意,IPython 和 Matlab 一样允许纯退出。因此,在 Julia 中允许混叠是合理的。 感谢您提供有关如何执行此操作的任何想法。 最佳答案 退出 Juli
我正在运行Django服务,该服务将启动chromedriver用于 Selenium ,并爬取网站以获取数据。 另一个Java服务通过HTTP调用Django服务。 这是代码: views.py p
Iam在我的游戏中一起使用Adcolony和Vungle时,一切正常,但是当用Application.Quit()游戏退出游戏时,关闭了游戏,但弹出了文本“不幸的应用程序崩溃”的弹出窗口。 在这里我附
我最近做了一个小游戏,然后用pyinstaller把它变成了一个应用程序。运行时,有两种关闭方式。它是全屏的,因此不包括单击红色 x 按钮,但基本上我有这个 if keys[pygame.K_ESCA
我正在练习使用递归,但有些东西我不太明白。例如,我写了这个简单的倒计时函数,它应该等到一秒过去,然后倒计时到下一秒。 我首先是这样写的: function countdown(sec) { con
我正在使用 Appium 安装应用程序。安装后,应用程序应该在后台运行。另一项测试应使用 Chrome 在应用程序在后台运行时检查互联网连接。问题是 driver.quit() 甚至启动 Androi
我有一个正在运行测试的框架;任何错误都会导致 WebDriver 实例调用类似 handleException 方法的方法,我在其中调用 driver.quit() 方法。我觉得 driver.qui
我知道所有基本的处理程序,即 on run、on open 和 onreopen。但是这个处理程序,on quit,让我很困惑。我的问题是,它的用途是什么以及它是如何触发的? 最佳答案 on quit
我有两个 for 循环: for event in pygame.event.get(): if event.type == QUIT:
我目前正在编写一个小的 GUI 程序,它可以完成一些工作并在之后退出。工作完成后,GUI 线程会更新用户的信息。 这是我目前使用的模式,我认为它不是最优雅的模式: static void MainFo
我是一名优秀的程序员,十分优秀!