C# Async Examples in F# – Part 2

This post is the second of a series where I am converting the C# 101 Async Samples into F#. See below for the other entries in the series:

C# Async Examples in F# – Part 1

C# Async Examples in F# – Part 3

The second C# Async example deals with making multiple asynchronous web requests in serial. It’s pretty similar to the first example, but the nature of the example makes a few differences between the C# and F# async models more obvious.

Lets start with the C# sample:

public async void AsyncIntroSerial()
{
    var client = new WebClient();

    WriteLinePageTitle(await client.DownloadStringTaskAsync(new Uri("http://www.weather.gov")));
    WriteLinePageTitle(await client.DownloadStringTaskAsync(new Uri("http://www.weather.gov/climate/")));
    WriteLinePageTitle(await client.DownloadStringTaskAsync(new Uri("http://www.weather.gov/rss/")));
}

I’ll first show the simplest possible approach to convert it to F#:

let AsyncIntroSerialWithCodeSmell = async {
   let client = new WebClient()
    
   let! result1 = client.AsyncDownloadString(Uri("http://www.weather.gov"))
   this.WriteLinePageTitle result1
   
   let! result2 = client.AsyncDownloadString(Uri("http://www.weather.gov/climate/"))
   this.WriteLinePageTitle result2
    
   let! result3 = client.AsyncDownloadString(Uri("http://www.weather.gov/rss/"))
   this.WriteLinePageTitle result3
}

This approach is clearly smelly. F# evaluates async expressions using the let! syntax which also binds a name to a value. That means that you need to create a temporary variable to store the result of each async download. This was also true in the first async example, but it’s significantly more ugly here. Fortunately, you can easily rewrite this code to clean things up.

let AsyncIntroSerial = async {
    let client = new WebClient()
    
    let readAndWrite url = async {
        let! result = client.AsyncDownloadString(Uri(url))
        this.WriteLinePageTitle(result)
    }
    
    do! readAndWrite "http://www.weather.gov"
    do! readAndWrite "http://www.weather.gov/climate/"
    do! readAndWrite "http://www.weather.gov/rss/"
}

You can take advantage of F#’s support for nested function definitions and closure to rewrite the code in a DRY manner. I like this refactoring, but I do wish that F#’s computation expression builder syntax allowed me to run an async operation inline like the C# await syntax.

This entry was posted in Async, C#, F#. Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

One Trackback

  1. [...] //TODO: – Chris Marinos' Blog Skip to content AboutOpen Source « Five Reasons the MVP Summit was Awesome C# Async Examples in F# – Part 2 » [...]

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>