我该如何用 F# 编写以下内容?
var reader = await someDatabaseCommand.ExecuteReaderAsync();
while (await reader.ReadAsync())
{
var foo = reader.GetDouble(1);
// ...
}
Run Code Online (Sandbox Code Playgroud)
我对 F# 很陌生,所以这是我能想到的最好的方法
task {
let! reader = someDatabaseCommand.ExecuteReaderAsync ()
let! tmp1 = reader.ReadAsync ()
let mutable hasNext = tmp1
while hasNext do
// ...
let! tmp2 = reader.ReadAsync ()
hasNext <- tmp2
}
Run Code Online (Sandbox Code Playgroud)
我知道它是一个 C# 库,所以它不会是完美的,但我想避免需要将结果存储ReadAsync在变量中,更不用说有两个临时变量了。我不知道有什么方法可以在Task不将其绑定到名称的情况下获得 a 的“结果”。也许递归解决方案会起作用?
await该库与 C# 配合得非常好,因为您可以在循环条件中使用。我认为在 F# 中使用递归计算表达式比命令式解决方案好一点(我认为您无法简化它),但长度大致相同:
task {
let! reader = someDatabaseCommand.ExecuteReaderAsync ()
let rec loop () = task {
let! hasNext = reader.ReadAsync ()
if hasNext then
// ..
return! loop () }
return! loop ()
}
Run Code Online (Sandbox Code Playgroud)
更复杂的解决方案是使用 F# 异步序列(来自FSharp.Control.AsyncSeq 库)。我认为这只适用于async(所以你必须使用它而不是task),但它使代码更好。您可以定义一个运行命令并返回异步结果序列的函数(为简单起见,我只返回reader,这有点脏,但有效):
#r "nuget: FSharp.Control.AsyncSeq"
#r "nuget: System.Data.SqlClient"
open FSharp.Control
let runCommand (cmd:System.Data.SqlClient.SqlCommand) = asyncSeq {
let! reader = cmd.ExecuteReaderAsync () |> Async.AwaitTask
let rec loop () = asyncSeq {
let! hasNext = reader.ReadAsync () |> Async.AwaitTask
if hasNext then
yield reader
yield! loop () }
yield! loop () }
Run Code Online (Sandbox Code Playgroud)
for鉴于此,您可以使用内部普通循环很好地迭代结果async(使用 AsyncSeq 库添加的重载):
async {
for reader in runCommand someDatabaseCommand do
let foo = reader.GetDouble(1)
() }
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
400 次 |
| 最近记录: |