When Visual Studio 2010 was released and it included a large number of great new features, one of which in particular was portrayed as a stealth revolution by an article in The Register: F#. F# is a new .NET based functional programming language which emerged from Microsoft’s Cambridge Research lab as the primary focus of Don Syme. F# is a major new first class .NET language citizen which is now built into the VS2010 product. The language takes a lot of inspiration from OCaml. Anders Hejlsberg recently spoke very encouragingly about it in his Future Trends in Programming languages talk at TechDays in Belgium, which is certainly worth watching if you haven’t seen it before. I’ve only been playing with F# for a while but it’s pretty nice and it’s certainly worth looking at functional programming if you haven’t already if only because it’s an interesting set of new techniques and requires a slightly different approach to problems.
The F# compiler and libraries were also recently released as Open Source under the Apache 2.0 license which should make for some exciting developments in the future, not to mention better support for Mono.
I also found F# a good way to understand the slightly functional constructs that appeared in Delphi Prism 2011. I’ve only just started beginning to learn F# but I thought I would highlight some of the particularly interesting differences that I’ve found compared to Delphi.
Identifiers and let bindings
Identifiers are the way which you assign names to your values so that you can reference them later, using the let keyword. To a Delphi programmer this may sound like the concept of variables, however there is one important difference in F#: Variables are immutable and therefore normally can’t be changed and once a value has been assigned to it. Consider the following:
open System let x = 1 printfn "%d" x let x = 2 printfn "%d" x
This will produce a compiler error where we attempt to reassign a new value to the identifier x. F# shares the type inference approach of C# 3.0 onwards so you do not need to explicitly declare the types of your variables as you do in Delphi (while Delphi Prism shares the C# approach). It should also be noted that as in Delphi, you can also assign identifiers to methods. For example, in Delphi you might do something like the following:
var i: integer; myAdder: TFunc<integer, integer, integer>; begin myAdder := function(a, b: integer): integer begin result := a + b; end; i := myAdder(1, 2); end;
The equivalent F# code might look like this where F# Functions are values in their own right anyway:
// Could also be written in longform as: // let myAdder = fun a b -> a + b let myAdder a b = a + b let i = myAdder 1 2
If you’re coming from Delphi, it is also worth noting that identifier names are case-sensitive.
F# defines scope, by default, using whitespace and indentation creates new scope, and the end of that particular scope is signaled by the end of the indented block. The following example demonstrates this, by reusing the identifier ‘z’ as a midway calculation half way through a block.
let z = 1 let y = let z = 3 * 2 z / 2 printfn "%d" y
This code also demonstrates that like the Ruby language, you do no need to explicitly state a return value for a method. This can be quite freeing in many ways.
It should also be noted that you can redefine identifiers with the let keyword whilst in the scope of a function.
Another favoured building block for functional programming is pattern matching. A very simple example of this might be compared to series of case or if statements in Delphi. For example, if we look at an implementation of the FizzBuzz problem in Delphi:
// if ((i mod 15 = 0)) then if ((i mod 3 = 0) and (i mod 5 = 0)) then begin WriteLn('FizzBuzz'); end else if (i mod 3 = 0) then begin WriteLn('Fizz'); end else if (i mod 5 = 0) then begin WriteLn('Buzz'); end else begin WriteLn(i); end; end;
And then using pattern matching in F#:
// FizzBuzz Solution - @jamiei open System let FizzBuzz() = let nums = [1..100] let printbuzz x = match x with // | x when x%15=0 -> printfn("FizzBuzz") | x when x%3=0 && x%5=0 -> printfn("FizzBuzz") | x when x%3=0 -> printfn("Fizz") | x when x%5=0 -> printfn("Buzz") | _ -> printfn "%d" x; nums |> List.iter(fun x -> printbuzz x) FizzBuzz() let _ = Console.ReadLine()
Pattern matching must either be complete (i.e. must match all possible values of an identifier) or incomplete and include a wildcard (“_” in the above example) or the compiler will raise an exception at runtime. The compiler will also emit a warning for rules which will never be matched.
let rand = new Random() let randNum = rand.Next(0, 100); let coinToss = match randNum % 2 = 0 with | true -> "heads" //| false -> "tails" printfn "%A" coinToss
Pattern matching may appear to be a simple tool but it’s an extremely concise way of controlling the flow of an application, particularly to get rid of what would otherwise turn into a spaghetti ball of if statements. Pattern matching can also be active, which means that they allow you to execute a function to determine the match.
Units of measurement
If you were listening carefully to the Podcast of Delphi.org when marc hoffman was talking to Jim McKeeth about the future of Delphi Prism, you’ll remember that he mentioned that this might be coming to Delphi Prism. This represents a pretty nifty way of marking the units of a value which makes you less likely to accidentally make a mistake when combining them with less effort than in Delphi where you would have to declare and create a class for each. The following code in F#, will throw an exception:
[<Measure>]type centimetre [<Measure>]type inch let distanceToMyThumb = 1<inch> let distanceToMyOtherThumb = 2.5<centimetre> let newVol = distanceToMyThumb + distanceToMyOtherThumb
F# is a very expressive language and the more I read and use it, the more I find that the expressions and constructs that it allows give me new ways to think about certain problems. It is also great that it is built upon the .NET Framework and can interact fully with the standard .NET libraries. My F# test modules can also interact with and be interacted by any Delphi Prism applications that I need it to. If your curiosity is piqued by functional programming and you are already familiar with the .NET framework then F# is a great way to try your hands.
You can find more information on F# here: