People have been known to ask me, what makes F# better than C#? This is a since what people think is good or bad about a programming languages just comes down to taste. However Alejandro Serrano blog post about how an F# typeof operator can be defined got me thinking about things you can do in F# that you can in C#. In it he describes how you can define a typeof operator for F#, this is something you can not do it C# the type of function is build in to the compiler and can not be defined as a method.

 

While the typeof operate cheats slightly by utilising F# ability to mix IL source into a F# source file, there are a couple of other operators which replicate functionality build into the C# compiler as pure F# functions. These functions are using and lock, both in F#’s Microsoft.FSharp.Idioms namespace. Let’s take a quick look at the using function; F# defines this to be:

 

let using (ie: System.IDisposable) f =

  try f()

  finally ie.Dispose()

 

One would typically use this something like:

 

open System.IO

open Microsoft.FSharp.Idioms

 

let _ = let writer = File.AppendText("text.txt") in

            let f() =

                        writer.WriteLine("written in a safe way") in

             using (upcast writer) f

 

So we define some a reference to an object that refers to some unmanaged resources, that is a stream writer in the line “let writer = File.AppendText("text.txt")”, then we defines some operations on it, that is the “let f() = …”, then we use the using function to say we’d like the operations to happen then have the object disposed of in a finally block.

 

So why can we do this in C#? The using statement in C# relies on macro like expansion from the C# compiler, so:

 

using(StreamWriter writer = File.AppendText("text.txt"))

{

            writer.WriteLine("written in a safe way");

}

 

Expands to:

 

StreamWriter writer = File.AppendText("text.txt");

try

{

            writer.WriteLine("written in a safe way");

}

finally

{

            writer.Dispose();

}

 

You can not do this kind of thing in C# code because C# does not allow you to pass a method as a value; making is impossible insert a function call into the middle of the method unless you resort to using delegates.

Feedback:

Feedback was imported from my only blog engine, it's no longer possible to post feedback here.

re: The Expressiveness of a Language - Don Syme

Hi Robert,

Once you get used to it doing this sort of abstraction-of-control-patterns in F# is very nice.

Just to note that with the type checking features added in F# 1.0.4 the code above can now be written:

let writer = File.AppendText("text.txt") in
let f() = writer.WriteLine("written in a safe way") in
using (writer) f

or I prefer to use an inline function with a begin/end pair:

let writer = File.AppendText("text.txt") in
using (writer) begin fun () ->
writer.WriteLine("written in a safe way")
end

Cheers!
Don