我是F#的初学者,所以这是一个简单的问题,也许是重复的,但我无法在任何地方找到答案......
我正在阅读this LOGO DSL implementation但我不明白,“做什么!”是什么意思。这里的符号:
this.Loaded.Add (fun _ ->
async {
do! Async.Sleep 200
for cmd in theDrawing do
do! this.Execute(cmd)
} |> Async.StartImmediate
)
你能帮忙吗?
答案 0 :(得分:20)
我只会补充说,计算表达式不必显式支持do!
表示法,因为可以使用let!
编写相同的内容,如下所示:
do! foo() // Using do!
let! _ = foo() // Equivalent using let!
一般来说,let!
当我们使用计算表达式实现某些函数并且你想从另一个相同类型的计算表达式中调用它时使用。这意味着,它用于组合计算表达式。对于async
,此组合表示您具有非阻塞异步代码,并以某种特殊方式从另一个异步工作流调用它以使调用异步。
let!
关键字允许您执行此操作并获得一些值作为结果,而do!
是一个快捷方式,如果计算不返回任何内容,您可以使用它。
真实世界函数式编程中讨论计算表达式(以及序列表达式)的章节可作为免费样本提供,因此如果您想阅读有关计算表达式的更详细的教程,这可能是是一个很好的信息来源:
BTW:应该可以使用AwaitEvent
原语以更好的方式在您的问题中编写示例代码:
async {
let! _ = this.Loaded |> Async.AwaitEvent
do! Async.Sleep 200
for cmd in theDrawing do
do! this.Execute(cmd) } |> Async.StartImmediate
这意味着同样的事情 - 它首先等待Loaded
事件发生,然后它等待200ms,然后它完成其余的工作。这个等待是特殊的(这就是我们使用let!
/ do!
的原因,因为它在等待时不会阻塞线程。
答案 1 :(得分:9)
F#computation expressions(a.k.a。“workflows”)使用语法
builder { expression }
其中expression
可以包含特殊构造,包括let!
和do!
等各种“爆炸”关键字。就像C#或VB中的LINQ一样,F#计算表达式只是一个语法糖(在builder
上进行方法调用)。
最常见的计算表达式之一是async
,如here所述。
在此特定示例中,async
与Async.Sleep
一起使用以暂时脱离UI线程,为UI提供重绘机会,对鼠标事件作出反应等。技术更多地描述here。
答案 2 :(得分:3)
在你的情况下,它正在异步运行sleep表达式,因此线程可以做一些有用而不是阻塞的事情。
通常,let!
,use!
,yield!
和do!
执行包含计算表达式的“特殊”处理(无论是async
在这种情况下)。例如。在使用seq { ... }
的{{1}}中,允许将子序列合并到输出中,而不是作为单个对象返回。