Saturday, April 04, 2009 9:42 PM
Discoveries This Week 04/03/2009
With the start of our F# User’s Group this next Monday and New England Code Camp 11 last weekend, things have been extremely busy this past week. Meanwhile, the F# sociocosm is growing at a rapid pace. This week we have a talk by Don Syme, a look at F# quotations, and finally, some discussion on Seq.unfold.
A shameless plug here for our new user group. A big thanks to Chris for helping us find the resources we needed to start out. Without him this might never have come together.
As Don Syme is the father of F#, when he speaks the community listens. In this talk Don focuses on the pleasure and speed inherent in using FP and F#. He does this by describing the functional methodology and constructs which provide a simpler and more elegant model for building programs.
A simple example on the surface for sure. However, if you haven’t seen the power of F#’s language oriented programming features this is sure to be of interest.
For a deeper look at the power of quotations check out Tomáš Petříček’s F# quotations visualizer. If his past projects are any indication Tom’s upcoming book is a must have for any F# enthusiast. I preordered a copy just today.
One of the most fantastic things F# has to offer is the rich functional programming heritage of sequence operations. To demonstrate how elegant they can make your code, I would like to offer the following alternative F# solution:
let fibs =
Seq.unfold (fun (a, b) -> Some( a, (b, a+b) )) (0I, 1I)
Seq.find (fun n -> n >= 10I ** 999I ) fibs
I’m going to take this opportunity to point out the obvious: we have here two lines of F# which does almost exactly the same thing as thirty six of C#. Now that’s what I call power and elegance. The unfold function pretty much does exactly what yield was doing before, but implicitly in terms of the unfold function. The idea of unfold can be confounding at first and so here is a breakdown of how it works:
let fibs =
(fun (a, b) -> //generator function,
//(a, b) is the previous state
Some //Option monad, needed for unfold
(a, (b, a + b))) //returned tuple: (value, state)
//or (first, (second, third))
(0I, 1I) //Initial function state (first, second)
Note that in this version the state of the next two values in the sequence are always pre-calculated. However, it is easy to avoid this if you instead consider the state in terms of the previous two values:
let fibs =
Seq.unfold (fun (l, l2) ->
let n = l + l2 in Some( n, ( n, l ) ))
(0I, 1I) //(previous, second previous)
If you want to learn more about unfold I recommend checking out:
This is the best description of how unfold works I’ve seen to date.