I spent a bunch of time over the holidays getting to know F# a bit better. I think I now consider myself to be truly dangerous with it.
A couple of things which repeatedly bit me as I stumbled through learning F# as a n00b.
Don’t forget the ‘=’ or the “rec”
First the dumb stuff…
A couple of things I found myself doing a lot when I first started. Most often was forgetting the ‘=’ at the end of the first line of a let function binding. The IDE will show an error for this, usually “Unexpected …. in binding. Expected ‘=’ or other token”.
Similarly recursive functions need to be labeled correctly. In this case the missing rec caused a “The value or constructor … is not defined” error for each reference to my recursive function. As with missing ‘=’ I found myself staring stupidly at the code trying to figure out what was wrong.
Module ordering matters
The order your F# source files appear in the solution matters! The project shown on the right doesn’t compile because the file OctreeTests.fs includes an open statement which refers to the module defined in Octree.fs. But—and here’s the gotcha—the tests file appears first in the list and thus gets compiled first! You’ll see an error on the open statement; “The namespace or module … is not defined”.
You can fix this by right clicking on either file and using the “Move Up” or “Move Down” menu items to correct the order. If you come from a C# background this isn’t the expected behavior.
Equality means structural equality
Equality in F# is treated a bit differently than C#. Consider the following two unit tests which compare lists. First in C#; two identical lists evaluate as not equal.
Now lets do the same with F#. In this case the lists evaluate as equal.
In other words F# uses structural equality not referential equality by default. In most cases this is probably what you want but in some cases it may not be. For instance if the lists are very long then this may be time consuming so in some cases you might want to provide a referential equality operator if your algorithm is OK with comparing instances not their values.
Test driven development with TestDriven.NET and xUnit
One of the best things I discovered about F# was that xUnit.net now supports Fact attributes on static methods. Thanks to Harry and Matt for prompting Brad and Jim to add this to the latest versions of xUnit.net. This means you can write code like this right in your F# project:
If you use TestDriven.NET as your test runner then you might be tempted to right click on a test and try and run it.
Turns out that TestDriven.NET can get a bit confused by modules and namespaces. If you specify both the module and the namespace in your tests file TD.NET will give you an error something like “TestCase ‘T:Tests’ failed: Couldn’t find type with name ‘Tests’”.
The workaround for this is to specify the module name only, not the namespace and a module.
The right click context menu should now work.
On a similar note; the Beta 2 drop of F# still includes the bug around decorating properties on interfaces which I blogged about a while back.