We've removed the tail recursion because it was hard to consolidate it into yield! (it was instead done with return!, which has no place in taskSeq).
However, today I helped someone with some code that he considered for taskSeq which had the following approach:
let getPoliciesAsync policyid =
asyncSeq{
use connection = new NpgsqlConnection(npgsqlConnectionStringBuilder.ConnectionString)
use command = new NpgsqlCommand($"SELECT policy_data FROM policy.tbl_policy where policy_id = {Sql.uuid policyid};", connection)
let! reader = command.ExecuteReaderAsync() |> Async.AwaitTask
let rec someRec() = asyncSeq{
let! rowExists = reader.ReadAsync() |> Async.AwaitTask
if rowExists then
yield {| dt1 = reader.GetString(0) |}
yield! someRec()
}
yield! someRec()
} |> AsyncSeq.toAsyncEnum
As you can see, it uses asyncSeq, but also: it is recursive. The same approach with taskSeq would likely be more performant, however, if there are a lot of rows, this becomes problematic. This code can be rewritten with a loop, though.
@dsyme, sharing this with you in case we want to revisit this at some point.
We've removed the tail recursion because it was hard to consolidate it into
yield!(it was instead done withreturn!, which has no place intaskSeq).However, today I helped someone with some code that he considered for
taskSeqwhich had the following approach:As you can see, it uses
asyncSeq, but also: it is recursive. The same approach withtaskSeqwould likely be more performant, however, if there are a lot of rows, this becomes problematic. This code can be rewritten with a loop, though.@dsyme, sharing this with you in case we want to revisit this at some point.