FShaper icon indicating copy to clipboard operation
FShaper copied to clipboard

Support async/await

Open willsam100 opened this issue 5 years ago • 2 comments

C# has native support for async/await, F# has async computation expressions. It should be possible to get close:

  • async in method -> async { ... }
  • await -> either let! or do! in the case of no binding. Expr will also require |> Async.AwaitTask

willsam100 avatar Apr 18 '19 19:04 willsam100

I also recommend generated async { ... } to end with |> Async.StartAsTask because some frameworks like WCF / SignalR / ... supports Task by default where as they don't await F# asyncs.

Thorium avatar Apr 23 '19 14:04 Thorium

@Thorium very good point. I have done this with the tests below.

I do wonder if supporting conversion to TaskBuilder would be better as it should be better performance, or to wait for native task support

Passing tests (more coverage may be needed):

[<Test>]
member this.``async no await writes as normal method`` () = 
    let csharp = 
         """public async void Foo ()
            {
                return;
            }"""

    let fsharp = 
         """member this.Foo() = ()"""
               
    csharp |> Converter.run 
    |> should equal (formatFsharp fsharp)

[<Test>]
member this.``async with await writes as async computation method`` () = 
    let csharp = 
         """public async void Foo ()
            {
                await Bar.WriteAsync();
            }"""

    let fsharp = 
         """member this.Foo() = async { do! Bar.WriteAsync() |> Async.AwaitTask } |> Async.StartAsTask"""
               
    csharp |> Converter.run 
    |> should equal (formatFsharp fsharp)

[<Test>]
member this.``await writes as async with let! in async computation`` () = 
    let csharp = 
         """public async void Foo ()
            {
                var x = await Bar.WriteAsync();
                return x;
            }"""

    let fsharp = 
         """member this.Foo() = async { return Bar.WriteAsync() |> Async.AwaitTask } |> Async.StartAsTask"""
               
    csharp |> Converter.run 
    |> should equal (formatFsharp fsharp)

[<Test>]
member this.``await writes as async with multiple let!`` () = 
    let csharp = 
         """public async void Foo ()
            {
                var x = await Bar.GetX();
                var y = await Baz.GetY();
                return x + y;
            }"""

    let fsharp = 
         """member this.Foo() = async { let! x = Bar.GetX() |> Async.AwaitTask
                                        let! y = Baz.GetY() |> Async.AwaitTask
                                        return x + y } |> Async.StartAsTask"""
               
    csharp |> Converter.run 
    |> should equal (formatFsharp fsharp)

willsam100 avatar Apr 27 '19 09:04 willsam100