gpt4 book ai didi

f# - 如何在 F# 异步表达式中使用 while 循环?

转载 作者:行者123 更新时间:2023-12-02 15:47:02 24 4
gpt4 key购买 nike

我将如何在 F# 中编写以下内容?

var reader = await someDatabaseCommand.ExecuteReaderAsync();
while (await reader.ReadAsync())
{
var foo = reader.GetDouble(1);
// ...
}

我是 F# 的新手,所以这是我能想到的最好的

task { 
let! reader = someDatabaseCommand.ExecuteReaderAsync ()
let! tmp1 = reader.ReadAsync ()
let mutable hasNext = tmp1
while hasNext do
// ...
let! tmp2 = reader.ReadAsync ()
hasNext <- tmp2
}

我知道它是一个 C# 库,所以它不会是完美的,但我想避免需要将 ReadAsync 的结果存储在一个变量中,更不用说有两个临时变量了。我不知道有什么方法可以在不将其绑定(bind)到名称的情况下获取 Task 的“结果”。也许递归解决方案可行?

最佳答案

此库与 C# 配合得很好,因为您可以在循环条件中使用 await。我认为在 F# 中使用递归计算表达式比命令式解决方案好一点(我不认为你可以简化它),但它的长度大致相同:

task {
let! reader = someDatabaseCommand.ExecuteReaderAsync ()
let rec loop () = task {
let! hasNext = reader.ReadAsync ()
if hasNext then
// ..
return! loop () }
return! loop ()
}

一个更精细的解决方案是使用 F# 异步序列(来自 FSharp.Control.AsyncSeq library )。我认为这只适用于 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 () }

鉴于此,您可以在 async 中使用纯 for 循环(使用由 AsyncSeq 库添加的重载)很好地迭代结果:

async { 
for reader in runCommand someDatabaseCommand do
let foo = reader.GetDouble(1)
() }

关于f# - 如何在 F# 异步表达式中使用 while 循环?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73806802/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com