F# 异步 while 循环累积的惯用转换
F# idiomatic conversion of async while loop accumulation
处理异步 while 循环累积的惯用 F# 方法是什么?
我正在使用新的(仍在预览中)Azure Cosmos DB SDK。查询数据库 returns a CosmosResultSetIterator<T>
其中有 HasMoreResults
属性 和 FetchNextSetAsync()
方法。我对 C# 代码的直接翻译如下所示:
let private fetchItemsFromResultSet (resultSetIterator: CosmosResultSetIterator<'a>) =
let results = ResizeArray<'a>()
async {
while resultSetIterator.HasMoreResults do
let! response = resultSetIterator.FetchNextSetAsync() |> Async.AwaitTask
results.AddRange(response |> Seq.toArray)
return Seq.toList results
}
我会看一下 AsyncSeq 包。您可以使用它来创建异步计算的序列,然后异步或并行地迭代它们。这允许异步绑定在序列内部并且 yield 异步发生,因此您不必显式构建累加器。
您可以使用它来执行以下操作:
open FSharp.Control
let private fetchItemsFromResultSet (resultSetIterator: CosmosResultSetIterator<'a>) =
asyncSeq {
while resultSetIterator.HasMoreResults do
let! response = resultSetIterator.FetchNextSetAsync() |> Async.AwaitTask
yield! response |> AsyncSeq.ofSeq
}
恕我直言,尾递归优于 while 循环,因为它是避免突变的一种方法。
例如:
let fetchItemsFromResultSet (resultSetIterator: CosmosResultSetIterator<'a>) =
let rec loop results =
async {
if resultSetIterator.HasMoreResults then
let! vs = resultSetIterator.FetchNextSetAsync () |> Async.AwaitTask
let vs = vs |> Seq.toList
return! loop (vs::results)
else
// List.rev needed because batches are in reverse
return results |> List.rev |> List.concat
}
loop []
处理异步 while 循环累积的惯用 F# 方法是什么?
我正在使用新的(仍在预览中)Azure Cosmos DB SDK。查询数据库 returns a CosmosResultSetIterator<T>
其中有 HasMoreResults
属性 和 FetchNextSetAsync()
方法。我对 C# 代码的直接翻译如下所示:
let private fetchItemsFromResultSet (resultSetIterator: CosmosResultSetIterator<'a>) =
let results = ResizeArray<'a>()
async {
while resultSetIterator.HasMoreResults do
let! response = resultSetIterator.FetchNextSetAsync() |> Async.AwaitTask
results.AddRange(response |> Seq.toArray)
return Seq.toList results
}
我会看一下 AsyncSeq 包。您可以使用它来创建异步计算的序列,然后异步或并行地迭代它们。这允许异步绑定在序列内部并且 yield 异步发生,因此您不必显式构建累加器。
您可以使用它来执行以下操作:
open FSharp.Control
let private fetchItemsFromResultSet (resultSetIterator: CosmosResultSetIterator<'a>) =
asyncSeq {
while resultSetIterator.HasMoreResults do
let! response = resultSetIterator.FetchNextSetAsync() |> Async.AwaitTask
yield! response |> AsyncSeq.ofSeq
}
恕我直言,尾递归优于 while 循环,因为它是避免突变的一种方法。
例如:
let fetchItemsFromResultSet (resultSetIterator: CosmosResultSetIterator<'a>) =
let rec loop results =
async {
if resultSetIterator.HasMoreResults then
let! vs = resultSetIterator.FetchNextSetAsync () |> Async.AwaitTask
let vs = vs |> Seq.toList
return! loop (vs::results)
else
// List.rev needed because batches are in reverse
return results |> List.rev |> List.concat
}
loop []