Having spent some time programming in F#, I though I’d post some observations that might be useful to C# programmers.
F# has an ambiguity with regard to the return statement. It’s not required in a function, but when you are in a match block, you do need it:
match root.Name.ToString() with
| "rss" -> return ProcessAsRss(root, url)
| "atom" -> return ProcessAsAtom(root, url)
| _ -> return 0
F# has something against null. Apparently, you cannot really have null objects without hacks. Which was a problem for me because I was trying to write
let id = null
to use it as an output parameter in a sproc. I got so confused I had to ask on SO, and ended up writing somewhat bizarre code:
let id = new Nullable<int>()
Somewhat predictably, the int? syntax is not working – F# tells me that the use of a ? symbol after an identifier is reserved for future use.
You cannot call a function that returns something and then continue doing things. Without the return statement, F# thinks that a returning function is the return value. Which leads to code like the following
let _ = ctx.ChannelUpsert(ref id, url,
⋮
)
The underscore stores the end result, even though we don’t really care.
One of the really useful methods for downloading from the web was removed from F# in order to allow for compatibility with Silverlight and Mono. This function defines a matching pair of Begin and End clauses for a web request, thus allowing asynchronous operation:
type WebRequest with
member x.GetResponseAsync() =
Async.BuildPrimitive(x.BeginGetResponse, x.EndGetResponse)
The async keyword is really fun syntactic sugar that also exists in C# (in a way) via PowerThreading’s AsyncEnumerator, though this usage is somewhat more clever. Essentially, in addition to an immediate variable-definition operator let, F# also has a ‘whenever’ operator let! (with an exclamation mark). This operator appears precisely at an async junction, i.e., on the left-hand side of an async call:
let UpsertFromUrl(url:string) =
async {
try
let r = WebRequest.Create(url)
let! resp = r.GetResponseAsync()
use stream = resp.GetResponseStream()
use reader = new StreamReader(stream)
let xml = reader.ReadToEnd()
⋮
}
It seems the whole point of async ops is to fire them off on arrays (sorry, sequences). It is this way in PowerThreading, and it appears this way in F#.
let UpdateExistingChannels =
use ctx = new PrioryDataContext()
ctx.Channels
|> Seq.map (fun f -> UpsertFromUrl(f.Source))
|> Async.Parallel
|> Async.Run
The funny thing is: I wonder how many people will use this instead of, say, doing Parallel.Invoke() instead. ← This is C# 4 library stuff, btw. We’re not even there yet.
F# has a use keyword to match C#’s using, but it’s not clear where its scope is. F# does not really delimit its scope with curly braces (exce, and indenting doesn’t help either. Figures.
Strings lose their == operator, so you can no longer compare them this way. Actually, I was also comparing string and XName and the like, and I suspect that I might have panicked. Also – and this is annoying – the compiler did not list the error! It just failed to compile and I had to check the build output to see what was going on. How crazy is that?!?
I managed my first F# hack!!! (err, of sorts) I was trying to do an upsert on all elements of an array, and then return the array, but whatever I did, F# was complaining that my List.iter code was not to its liking. So, instead, I used List.map taking the return value of my upsert sprocs and returning the length of that list. All in one statement. Witness my perfection:
first.Elements()
|> Seq.filter(fun f -> f.Name.Equals("item"))
|> Seq.map(fun f -> ctx.ItemUpsert(ref itemId, id,
⋮
)
|> Seq.length
Programming is great!