F# -- the 3 minute guide!
By popular demand, we're going to spend three minutes learning as much as we can about F#.
So what is F#?
F# is "a mixed functional/imperative/object-oriented programming language"
Sorry -- that description's meaningless to all but a handful of people. What I want to know is:
Is F# really "Fortran .Net?"
No! An earlier name for F# was: "Caml.Net" because this is essentially a ".Net" implementation of "Caml"
That doesn't help, unless you know what Caml is...
Caml is a popular French variation on the ML Programming language, where ML means 'meta-language'.
Then I take it F# has nothing to do with Sharepoint's Caml language?
Nothing whatsoever. It's unfortunate that the sharepoint team used that name. Enough said.
You know what? Let's just get our hands on the code...
(Continues)
If you've got the .Net Framework version 2.0, then all you need is F#:
- Go to The 'F# Releases' Page (currently 14.4 Meg for 'F# Compiler 1.1.11.7')
(or get a 'release candidate from here: F# Compiler 1.1.11.12 (14.2 Meg) (which I'll be using for my lernin.)
Download and unzip. You'll have a nice folder full of goodies.
As you can see there's an ".MSI" (microsoft installer file) included. Run that... and things should go smoothly.
(Oh wait... some problem with a missing file... a html file? Who cares? Ignore!)
It installs an interactive console, a visual studio plug in, a manual, release notes and samples.
Let's tinker with the F# Visual Studio plugin
Open visual studio 2005, go to the tools menu, "add in manager" -- and click the interactive F# tool, to load it.
Now there's a new tool window, not unlike the 'immediate window' that we know and love.
It contains this chunk of text:
MSR F# Interactive, (c) Microsoft Corporation, All Rights Reserved
F# Version 1.1.11.12, compiling for .NET Framework Version v2.0.50727
NOTE:
NOTE: Flags: --gui run a session with a GUI event loop.
NOTE: --exec just run the scripts on the command-line.
NOTE: Commands: #r <string>;; reference (dynamically load) the given DLL.
NOTE: #I <string>;; add the given search path for referenced DLLs.
{{blah, blah blah}}
NOTE: Bug reports to fsbugs@microsoft.com. Enjoy!
NOTE:
NOTE: Visual Studio key bindings:
NOTE:
NOTE: Up/Down = cycle history
NOTE: CTRL-C = interrupt session
NOTE: ALT-ENTER = send selected source text to FSI session (adds ;;)
I always like to skip past the rather bland hello world programs and straight onto my personal favourite:
> do print_endline "hello there ladies ;-)" ;;
hello there ladies ;-)
>
That certainly worked a treat. Not exactly inspirational stuff though.
Two crucial lessons in there: "do
" calls a function, while ";;
" seems to terminate a statement.
Never happy with just one implementation, i hit upon another way to achieve the same result...
I open a blank text file (in Visual Studio) and type the following:
do printf "ahh, we meet again\n"
I highlight this text and hit "[Alt] + [Enter]"
Magically, the output turns up in the interactive F# window!
Were you paying attention that time? I didn't type into the F# window. You can type in any window at all (within visual studio). Then highlight the text and press alt-enter
. The highlighted text is evaluated by the f# interactive tool. Nifty stuff.
Functions! Hurry Up with the Functions!
Oh, you want me to write a function in this functional language... yes i was hoping to avoid that.
Okay -- now I've written "My First Function" in F#, here it is:
let NextNumber x = x + 1
What I'm hoping this means is:
When I select the text of my little function, and hit Alt-Enter, the following text appears in the interactive window:
val NextNumber : int -> int
This is the 'signature' of the function, more or less. It means something like:
Fair enough. Now from the smidgen I know about functional programming, i know they do love their recursive functions. I soon find this keyword rec
, meaning recursive, which can be used for any function that defines it's output in terms of its input.
You'd prefer an example? Well let's write a function that adds up all the numbers from 1 to X.
And let's do it using recursion.
let rec sumto n =
if n < 2 then 1
else n + sumto(n-1);;
This one basically says:
Okay, now we can use our function like so:
sumto 100
Which returns the following result in the interactive window:
val it : int = 5050
(Twenty minutes on the calcu'later, i can confirm this to be correct.)
Notice that both the function we wrote earlier and this result we've just calculated are described as 'values'. I take this to be a sign of the way a functional programming language treats functions as first class citizens.
Now I can jump to something I've been wanting to demonstrate since the start. The |> operator. Let me put that in a heading:
The Pipeline Operator, |>
That's a bar symbol, followed by a greater than. And it's similar to the pipe operator you recall from your DOS-filled youth.
Instead of typing 'sumto 100
', as we did above, we could pipe the parameter into the function, like so:
100 |> sumto //returns the same values as 'sumto 100'... i.e.
val it : int = 5050
Here we've said something like: "direct the value 100 into the value 'sumto'"
We can use this logic to re-write the 'sumto
' function from above:
let rec sumto n =
if n>1 then
n + (n-1 |> sumto)
else 1
What's so important about this |> operator? Isn't it just a redundant little syntactic bit of acrobatics?
Yes and no, old buddy. Yes and no.
Imagine some deeply nested function calls, like so:
a(b(c(d(10)))) ;;
You've got to admit that it looks ugly, but also that it's horribly ass about. [That's a technical term for back-to-front].
"a(b(c(d(10))))" means "apply the function d to the value 10, then apply the function c to the result of that, then apply the function b to the result of that... and so on."A less ass-about syntax is:
10 |> d |> c |> b |> a ;;
The above code could be described as "direct the value 10 into the function d, then direct the result of that into the function c, then..." and so on.
It's easy to match the code with the description of what's happening. Or at least, easier than it would be if we used the original ass-about syntax ('a(b(c(d(10))))
')
(I fully expect that the preceeding pipeline operator description is completely wrong... I await a clarification from don syme, of course ;-) )
Okay -- that's as far as we can possibly get in three minutes. We didn't have as much fun with curry as i'd have liked.
I'll finish with some links for the intrigued reader:
F# links:
The best place to start: Quick Tour -- almost a cheat sheet.
resources
articles:
Dave Cooper's appropriately named article: F# - Combining the efficiency, scripting, strong typing and productivity of ML with the stability, libraries, cross-language working and tools of .NET.
- F# blog post from Rob Burke ("F# - a functional programming language, in more ways than one)
- C#, F# and SMLNET
My book "Choose Your First Product" is available now.
It gives you 4 easy steps to find and validate a humble product idea.