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