I enrolled in this course in July of 2012. I didn’t know much about functional programming, but a night of Clojure koans at Software Craftsmanship McHenry County and several articles (like this one by John Carmack) about the advantages piqued my interest, and when I saw this course offering, I leaped.
I didn’t really know what I was getting into, but there were several surprises in store for me.
First, the instructor was Martin Odersky, designer of Scala. I’m not always the sharpest Ginsu in the drawer, so the course had already started before I figured that bit out.
Second, if you don’t know much about functional programming, you might think, as I did, of recursion as something very useful in specific cases, but otherwise a waste of stack space. You need to quit thinking that; recursion is indispensable to functional programming, and once you’ve learned to write methods to exploit tail calls, they aren’t even hard on the stack.
Third, it can be frustrating (in a good way) to craft a functional solution to a problem that you *know* you could do imperatively in five minutes. In a way it feels like tying a hand behind your back, but once you get into the mindset, the functional solutions become much more natural.
Finally, this was one of the hardest things I have done since my qualifying exams in ’89. Getting my mind off a problem and letting a solution bubble up is a tool I have used many times in the past for really hard problems, and it’s something I found myself doing a lot in this course. Many exercises were solved in bed, just before I drifted off to sleep.
The course was more about functional programming and less about Scala, but I feel I should mention a few features of the language.
First of all, it is not a purely functional language — you can write imperative code in it, and since it is a JVM language, you can intermingle it with Java fairly easily.
Second, it’s got some really nifty features; in my opinion the niftiest of these is pattern matching. Basically, you define a function to do different things based on an expression. While this isn’t really anything you couldn’t do imperatively, the notation Scala uses is rather concise and easy to work with:
def combine(trees: List[CodeTree]): List[CodeTree] = trees match { case Nil => trees case List(x) => trees case x :: xs => insert(makeCodeTree(x, xs.head), xs.tail) }
What this code does is to merge the first two entries in a sorted list of trees into a larger tree. If the list is empty (the first case) or has a single element (the second) the function returns its argument.
The third case selects lists where there is a head (x) and a tail (xs — xs can technically be empty, but won’t here because we wouldn’t have fallen past the second case if it were). It then merges the head of the list, and the second element (here expressed as xs.head, ie the head of the tail of the list) and sticks it in the proper place in the list of remaining trees.
Overall, this was a great course. If you’re looking to learn some functional programming, or if you are just looking for a mental challenge that is missing from your day job, you should check it out. Another session starts on March 25, 2013.