When I was doing my A-levels way back in 1997 I often used to stay up late to listen to the Mark Radcliff Show in its grave yard shift phase on Radio 1. One catch phrase that does seem to be completely covered in the catch phrase guide is a “Another Quality Radio Item” although in later versions of the show this was shorten to “Quality Item” and used to refer to any feature on the show, I believe its origins came from when Mark and Lard would invite some guest on the show and they would proceed to have conversion about something very visual, realising the listener had no frame of reference they would stop themselves and say “Another Quality Radio Item” and then often carry on talking whatever they were talking about.
Anyway I digress, a week or so ago Scott Hanselman was kind enough to invite me on to his Hansel Minutes weekly pod cast to talk about F# and my book. I strongly believe that it will be put on the site tomorrow evening (10-08-2007), but I could be wrong.
The show was recorded late at night, my time anyway, and spent lot of time talking about F# syntax, which is as you can imagine quite visual. So this brought back strong memories of the Mark Radcliff Show and their Quality Radio Items.
Anyway so listens don’t get too lost I decided to post some examples of things we talking about. I’m doing this from memory so I might post some updates if there’s anything I’ve missed.
In F# most things are expressions, a lump code that returns a value, for example if ... then ... else in F# is an expression, not a statement, code with side effect, as it is in C# and VB.NET. This means the expressions on both side of the if expression must have the same time. It may sound like a small thing but it can actually catch quite a lot of errors before they happen, for example if the purpose of the if was to initialise an identifier one way or the other you cannot forget to initialise the identifier on one side. Here’s an example of an if expression in F#, initialising an identifier result in F# using an if expression:
let result =
if System.DateTime.Now.Second % 2 = 0 then
"heads"
else
"tails"
Next week talked about function as values, Scott rightly pointed out there are in many ways like delegates. However in F# things are simpler, we don’t need the over head of declaring a delegate type before we can pass the value around. To illustrate this take a look at the following F# function definition:
let myCleanup f =
try
f()
finally
cleanup()
This function, myCleanup, takes another function f, tries to perform it and always performs the cleanup function that I need to be called. To translate this into C# 2.0 would be easy, except you’d have to define a delegate with the type “void Function()”, the thing I find really annoying is that at least one function with the same signature already exists in the framework, ThreadStart, but we can use it simple because it has the wrong name and would give myCleanup users the wrong impression.
This leads me nice on to another thing we talked about the “hole in the middle pattern”, I first saw this talked about in this blog post (http://enfranchisedmind.com/blog/archive/2007/07/10/279), although I think its cropped up in a few other places too. It’s something you see quite often when programming, you may have several functions were you want to do the same thing at the start, the same thing at the end but a different bit in the middle. Passing in a function to do the work in the middle is a nice way to handle this, meaning you can refractor code so you don’t need any copy and paste reuse.
I guess related to this are map and fold functions that we talked about, they are just a very generally case of the hole in the middle pattern for working with lists. I tend to find most programs involve working with collections of one form or another, and there are standard things you want to do to a collection, like transform the collection or create a summary of it map and fold respectively are the that perform this action. Here’s what they look like in code:
Seq.map (fun x -> x + 1) [ 1 .. 10]
Seq.fold (fun acc x -> acc + x) 0 [ 1 .. 10]
([ 1 .. 10] is short hand for a list of integers 1 to 10).There are of course many other functions like map and fold that warp up other common function on lists.
We also so spend a bit of time talking about pattern matching. Which is a “switch statement on steroids”. “On steroids” because the offer everything a switch statement can do and more, like switch you can pattern match over values:
let matchInt x =
match x with
| 1 -> "one"
| 2 -> "two"
| _ -> "Buckle my shoe"
Unlike switch you can also pattern match over types:
let matchType x =
match box x with
| :? int -> "int"
| :? float -> "float"
| :? string -> "string"
| _ -> "other"
Related to pattern matching are union types. These allow you to create data types of related items that do not share the same structure. This may seem counter intuitive if you come from an OO back ground were related types always same the same common fields and decedents can only add new fields. However, it turns out the ability to have related types that do not share the same structure is really useful. One union type I use all the time when programming in F# is the option type, defined in the F# base libraries. This is what it looks like:
type option<'a> =
| Some of 'a
| None
This means it options is a value that can either be Some with one field of any type or None with no fields at all. This is a useful alternative to returning null, a programmer cannot forget to handle the “None” case in with an option type, they can with a null, and often do, leading to all the annoying null reference exceptions you see in testing. This is the option type in action:
let myMatch x =
match x with
| Some x -> any_to_string x
| None -> "<none>"
myMatch (Some 1)
myMatch None
It turns out union types are also very useful for describing computer languages, which leads us nicely on to the final topic we talked about: “language oriented programming”. Can mean several things in F#, it has its own lex and yacc implementation that integrate nicely with the compiler and make parsing text files as painless as possible. However often in F# when we talk about language oriented programming we mean creating embed domain specific languages (DSLs) using the languages data structures, particularly lists and union types. One such embed DSL is a DSL for creating a command line argument parser, an example of an arg parser defined this way is shown below. I really like this DSL as I find it a very intuitive way of creating an arg parser, and also because we have an abstract description of the parser we can use this to print out the usage statement when things go wrong.
#light
let myFlag = ref true
let myString = ref ""
let myInt = ref 0
let myFloat = ref 0.0
let (myStringList : string list ref) = ref []
let argList =
[ ("-set", Arg.Set myFlag, "Sets the value myFlag");
("-clear", Arg.Clear myFlag, "Clears the value myFlag");
("-str_val", Arg.String(fun x -> myString := x), "Sets the value myString");
("-int_val", Arg.Int(fun x -> myInt := x), "Sets the value myInt");
("-float_val", Arg.Float(fun x -> myFloat := x), "Sets the value myFloat"); ]
if Sys.argv.Length <> 1 then
Arg.parse
argList
(fun x -> myStringList := x :: !myStringList)
"Arg module demo"
else
Arg.usage
argList
"Arg module demo"
exit 1
Anyway that was a quick tour though F# ala Hansel Minutes, I hope you enjoyed it.
Feedback:
Feedback was imported from my only blog engine, it's no longer possible to post feedback here.
re: Another Quality Radio Item - lb
thanks for writing up this piece to accompany the show.
many technical podcasts could do with a written accompaniment in the same style.
top work, and good luck
lb
re: Another Quality Radio Item - 翻译公司
Good article.Thanks a lot.