Comparing F# with C#: Downloading a web page
In which we see that F# excels at callbacks, and we are introduced to the 'use' keyword
In this example, we will compare the F# and C# code for downloading a web page, with a callback to process the text stream.
We'll start with a straightforward F# implementation.
Let's go through this code:
The use of "open" at the top allows us to write "WebRequest" rather than "System.Net.WebRequest". It is similar to a "
using System.Net
" header in C#.Next, we define the
fetchUrl
function, which takes two arguments, a callback to process the stream, and the url to fetch.We next wrap the url string in a Uri. F# has strict type-checking, so if instead we had written:
let req = WebRequest.Create(url)
the compiler would have complained that it didn't know which version of
WebRequest.Create
to use.When declaring the
response
,stream
andreader
values, the "use
" keyword is used instead of "let
". This can only be used in conjunction with classes that implementIDisposable
.It tells the compiler to automatically dispose of the resource when it goes out of scope. This is equivalent to the C# "
using
" keyword.The last line calls the callback function with the StreamReader and url as parameters. Note that the type of the callback does not have to be specified anywhere.
Now here is the equivalent C# implementation.
As usual, the C# version has more 'noise'.
There are ten lines just for curly braces, and there is the visual complexity of 5 levels of nesting*
All the parameter types have to be explicitly declared, and the generic
TResult
type has to be repeated three times.
Testing the code
Back in F# land, we can now test the code interactively:
Finally, we have to resort to a type declaration for the reader parameter (reader:IO.StreamReader
). This is required because the F# compiler cannot determine the type of the "reader" parameter automatically.
A very useful feature of F# is that you can "bake in" parameters in a function so that they don't have to be passed in every time. This is why the url
parameter was placed last rather than first, as in the C# version. The callback can be setup once, while the url varies from call to call.
The last line (using List.map
) shows how the new function can be easily used in conjunction with list processing functions to download a whole list at once.
Here is the equivalent C# test code:
Again, the code is a bit noisier than the F# code, with many explicit type references. More importantly, the C# code doesn't easily allow you to bake in some of the parameters in a function, so the callback must be explicitly referenced every time.
Last updated
Was this helpful?