-
Notifications
You must be signed in to change notification settings - Fork 22
Description
Add while! (while-bang) keyword to computation expressions
I propose we extend the computation expression syntax with a new keyword, while!, that combines a let! and a typical while loop.
Using the current GRPC client as an example instead of writing something like...
task {
let! firstRead = sender.ResponseStream.MoveNext(ct)
let mutable read = firstRead
while read do
q.Push(sender.ResponseStream.Current)
let! nextRead = sender.ResponseStream.MoveNext(ct)
read <- nextRead
}
We should be able to do
task {
while! sender.ResponseStream.MoveNext(ct) do
q.Push(sender.ResponseStream.Current)
}
NOTE: That the typical approach for using recursion doesn't work for TaskBuilder's from my understanding since they aren't tail recursive in many libraries that provide them.
A similar problem exists when reading rows of an ADO.NET reader. If the while! syntax was allowed we would be able to do something like:
asyncSeq {
// https://docs.microsoft.com/en-us/dotnet/api/system.data.common.dbdatareader.readasync?view=netcore-3.1
while! reader.MoveNextAsync() do
yield {| Column1 = reader.GetInt32(0); Column2 = reader.GetInt32(1) |}
}
Instead of:
asyncSeq {
let rec yieldAsync() = asyncSeq {
// https://docs.microsoft.com/en-us/dotnet/api/system.data.common.dbdatareader.readasync?view=netcore-3.1
let! hasNext = reader.MoveNextAsync() |> Async.AwaitTask
if hasNext
then
yield {| Column1 = reader.GetInt32(0); Column2 = reader.GetInt32(1) |}
yield! yieldAsync()
}
yield! yieldAsync()
}
Pros and Cons
Pros: More concise code aiding readability, allows a more intuitive use of libraries exposing this pattern especially when given a Task API where using the recursive approach may not be supported, may offer a performance improvement for certain cases.
Cons: More work required to support this in the language and associated computational expressions (e.g. Task builders such as Ply).
Extra information
Estimated cost (XS, S, M, L, XL, XXL): S
Related suggestions:
Affidavit (please submit!)
Please tick this by placing a cross in the box:
- This is not a question (e.g. like one you might ask on stackoverflow) and I have searched stackoverflow for discussions of this issue
- I have searched both open and closed suggestions on this site and believe this is not a duplicate
- This is not something which has obviously "already been decided" in previous versions of F#. If you're questioning a fundamental design decision that has obviously already been taken (e.g. "Make F# untyped") then please don't submit it.
Please tick all that apply:
- This is not a breaking change to the F# language design
- I or my company would be willing to help implement and/or test this
For Readers
If you would like to see this issue implemented, please click the 👍 emoji on this issue. These counts are used to generally order the suggestions by engagement.