F#

You are currently browsing the archive for the F# category.

Microsoft Denmark have invited me to participate in JAOO 2008. If I in return spend some time in the Microsoft stand demoing F# and answering questions about F# and functional programming in general.

When Martin Esmann (Microsoft Academic Developer Evangelist) approached me, I told him that I’d be happy to show up, but I’m not using F# from within Visual Studio. In fact, I’m usually not even using Microsoft’s .NET implementation. I’m a happy Mono user. To Martin’s credit his initial reaction was that it would be cool that I demoed F# using Linux and Mono in the Microsoft stand.

However, after talking it over with his colleges, Martin got back to me and told me that they thought that using Linux and Mono to demo F# would send to mixed a message. I agree with that. So unfortunately I won’t be demoing Mono in a Microsoft stand this time. But I’ll of course bring my own laptop, and might show F# on Mono and Linux if there are questions about portability. Maybe I should contact the Mono guys and ask for a T-shirt, so that I silently can invite questions about Mono ;-)

Time to practice some F# demos.  Any suggestions for what would be effective? I’m planning to show of the brand new Units of Measure and also sequence comprehensions.

In my last post I showed how to decode morse code in Python using list comprehensions. In this post I will show how to do it in F# instead.

First using list comprehensions:

let codes =
    [("A",".-");   ("B","-..."); ("C","-.-."); ("D","-.."); ("E",".");
     ("F","..-."); ("G","--.");  ("H","...."); ("I","..");  ("J",".---");
     ("K","-.-");  ("L",".-.."); ("M","--");   ("N","-.");  ("O","---");
     ("P",".--."); ("Q","--.-"); ("R",".-.");  ("S","..."); ("T","-");
     ("U","..-");  ("V","...-"); ("W",".--");  ("X","-..-");("Y","-.--");
     ("Z","--..")]
let rec decode input =
    if input = "" then [""]
    else [ for c, code in codes when input.StartsWith(code)
           for rest in decode(input.Substring(String.length code))
           -> c + rest ]

As it can be seen the code is almost identical to the Python code. Incidentally, I could not find a function equivalent to Python’s startswith method in the O’Caml standard library (without using regular expressions). Fortunately F# came with one from the .NET library.

Much to my the surprise the compiled F# (running on Mono 1.2.4) is 4 times slower that the Python code. I then rewrote the program to use sequence comprehensions:

let rec decode input =
    if input = "" then { -> "" }
    else { for c, code in codes when input.StartsWith(code)
           for rest in decode(input.Substring(String.length code))
           -> c + rest }

This version runs faster, and uses only a constant amount of memory. Still the Python version is three and half times faster.

I then tried to run the programs on an other computer with Microsoft’s .NET implementation. This improved the F# running times a lot. However, they are still 40% to 80% slower than the Python version.

Chart of F# vs Python on morse code decoding

My current guess is that Python is much better at handling strings than .NET.

The actual numbers:

Linux, Mono Vista, MS .NET
Program Time
sec
Ratio Time
sec
Ratio
morse.py 7.94 ± 0.05 1 11.03 ± 0.03 1
morse.fs 33.07 ± 0.19 4.17 19.65 ± 0.33 1.78
morse-seq.fs 28.1 ± 0.59 3.54 16.12 ± 0.36 1.46

Update 2007-11-12 Added test files: