Consider tail recursion
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.
Yes, this should be rewritten with a loop
@abelbraaksma BTW I think I am going to prioritise an F# 8 addition to allow builders to specify ReturnFromTailcall or YieldFromTailcall methods.
@dsyme that would certainly simplify an addition like this, and would also allow task to support tail calls. Awesome! We can do some early-adoption testing here through TaskSeq.
See https://github.com/fsharp/fslang-suggestions/issues/1006 instead.