I’ve been doing object oriented programming since 2002. I’ve been looking to expand my horizons for a little while. Not that I believe OOP is bad. I have found that in some cases, modelling everything in classes can be extremely difficult and you end up with an over engineered and complex solution (usually by accident).
I started tinkering with Erlang around 2013. I really enjoy Erlang. I like the syntax, and the pattern matching is absolutely fantastic. I am also a fan of the actor model. My only issue is the problems I am solving for work don’t fit Erlang solutions (yet). Currently we primarily create desktop applications. The newer applications are in C#.
This is where F# comes in. F# is a functional language which runs on the CLR. This means you can start using F# and have it interop easily with your existing .Net applications. Below are a few reasons I started using F# over C#.
REPL (Read Evaluate Print Loop)
One advantage to using F# is the REPL. This allows you to get immediate feedback during your development process. Write a function, test it in the REPL. Modify the function, test it again. No compiling and no external test runner is required. A more apt definition of REPL would be Rapid Evolving Program Logic.
I like F#’s pattern matching. It can be concise and easier to read than a bunch of
if statements. An example is comparing application versions to determine if the user requires an update.
// uMaj, uMin, uBld = user's Major, Minor, Build version // lMaj, lMin, lBld = latest Major, Minor, Build version // C# if (uMaj < lMaj) return "Major"; else if (uMaj == lMaj && uMin < lMin) return "Minor"; else if (uMaj == lMaj && uMin == lMin && uBld < lBld) return "Build"; else return "None"; // F# - The user's version numbers are either matched or // bound to x for comparison match (uMaj, uMin, uBld) with | (x, _, _) when x < lMaj -> "Major" | (lMaj, x, _) when x < lMin -> "Minor" | (lMaj, lMin, x) when x < lBld -> "Build" | (_, _, _) -> "None"
F# tries to eliminate null values as much as possible. Nulls are still needed for working with non F# libraries. When an F# function needs the ability to return a value or no value (if there is an error), you can use the Option type. When the function returns a value you wrap it in
Some, when no value is to be returned you use
None. This gives you a function having a return of either Some (value) or None. A simple example of this is a divide function.
let divide a b = match b with | 0 -> None | _ -> Some (a/b)
After obtaining the result, you can use pattern matching to determine whether you received Some value or None. You end up with fewer NullReferenceExceptions by using options.
There are more reasons to use F#, discriminated unions, agents, and it’s fun. After a little practice and experience with F#, you find you write less code to accomplish the same task than in other .Net languages. All you need to know to get started with F# is the keywords “
|>” (pipe forward), and “
fun“. Happy learning!
Great F# resources: