3 Tips for More Elegant Let Bindings in F#
Probably the first keyword you picked up if you have learned any F# is the let
keyword – allowing you to bind identifiers to values or functions.
Here we bind hello
to a string value and square
to a function, and naughty
to a mutable integer.
let hello = "hi"
let square x = x * x
let mutable naughty = 5
But the let
keyword has a few addition tricks up its sleeve you might not be aware of if you’re an F# beginner. Here’s a few of my favourites:
Tuple Bindings
First of all, you can bind more than one value in a single statement very elegantly by using tuple pattern matching. A great use case would be for width
and height
values which naturally belong together:
let width,height = 300,200
in Bindings
Another handy trick which I stumbled across in this nice WAVE file generating snippet from Phil Trelford is to use the in
keyword to allow you to bind a value to a name and then use it in the same expression.
Say we’re using a BinaryWriter
and want to write an integer value to a file. We probably would want to avoid using magic numbers directly since it doesn’t help the reader know what the significance of the number is:
writer.Write(16)
We could change it to this to make the meaning of 16 more explicit, but at the cost of using two lines:
let headerSize = 16
writer.Write(headerSize)
However, with the in
keyword we can keep our code all on one line, but nicely readable:
let headerSize = 16 in writer.Write(headerSize)
Fake Immutables
Sometimes in F# you’ll be creating instances of mutable objects from other .NET assemblies, and it always feels a shame to have to write code to construct an instance and then mutate it when you’re trying your best to stay immutable.
I ran into this a lot recently doing some WPF in F#. Often you create a framework element, and then set some properties like this:
let p = new Polyline()
p.Stroke <- Brushes.White
p.StrokeThickness <- 2.0
If only there was a constructor that took those properties. Well, F# has a cool syntax that lets you pretend there is! Simply add them as named values in the new expression like this:
let p = new Polyline(Stroke = Brushes.White, StrokeThickness = 2.0)
Very nice, and lets you keep the naughty <-
operator out of your nice pure functional code!