F # идиоматическое преобразование асинхронного во время накопления цикла - PullRequest
4 голосов
/ 27 марта 2019

Каков идиоматический способ F # обработки асинхронного накопления цикла while?

Я работаю с новым SDK Azure Cosmos DB (все еще в режиме предварительного просмотра).Запрос к базе данных возвращает 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
    }

Ответы [ 2 ]

4 голосов
/ 27 марта 2019

Я бы взглянул на пакет AsyncSeq . Вы можете использовать его для создания асинхронно вычисляемых последовательностей, а затем повторять их асинхронно или параллельно. Это позволяет асинхронному связыванию находиться внутри последовательности, а выход происходит асинхронно, поэтому вам не нужно явно собирать аккумулятор.

Вы можете использовать это, чтобы сделать что-то вроде:

open FSharp.Control

let private fetchItemsFromResultSet (resultSetIterator: CosmosResultSetIterator<'a>) =
    asyncSeq {
        while resultSetIterator.HasMoreResults do
            let! response = resultSetIterator.FetchNextSetAsync() |> Async.AwaitTask
            yield! response |> AsyncSeq.ofSeq
    }
2 голосов
/ 27 марта 2019

ИМХО хвостовая рекурсия предпочтительнее циклов 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 []
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...