Thinking Functionally

Every programmer has a story about how he got his start.  My own journey began at age 14 when I was bored to death while completing a second-year algebra assignment.  My father who was working on the couch with a brand new laptop showed me that I could write a program to do the work for me.  I instantly fell in love with the idea and have been rediscovering that love ever since.

I first began programming in BASIC.  It didn't take long to learn BASIC.  Within a matter of days, I had written a few adventure games, a prime number sieve, and a menu system.  I had come to embrace GOTO statements.  Hopefully, my brain hasn't sustained irreparable damage.

Within a few months of learning BASIC, I wanted to learn something else a little more lean and mean so I started to learn C.  The process was extremely painful.  I still remember feeling at times the strong desire to just give up and go back to BASIC.  I felt this when the concepts just didn't sink in or when they did sink in but I wasn't as proficient at "doing it in C" as I was at "doing it in BASIC".  When confronted with a new programming task, my instinct was to run off and do it in BASIC but I forced myself to learn to do it in C and within a month or two I had not only met my previous ability in BASIC but far surpassed it.  New opportunities were open to me after I made the change.

As silly as this sounds now, when I first started the transition from BASIC to C, I wasn't even sure that it was possible.  It was an act of faith to proceed to learn something that I wasn't even sure would payoff.  After seeing the tremendous benefit at the end of the proverbial rainbow, I vowed that I would never let pain and difficultly get in the way of accomplishing something new.

The lesson has been repeated throughout my life.  I remember another time when I first began riding seriously (mountain biking).  It was painful.  I would approach the bottom of a seemingly endless hill and whimper inside at the prospect of climbing it.  After the ascent began it was only worse.  My whole body screamed at me to drop the bike and walk up the hill, but I persevered.  In the end, it was the constant perseverance that strengthened my muscles, my lungs, and my confidence such that I wasn't daunted by the hills anymore.  In fact, I soon came to love the hills that put my strength, endurance, and determination to the test.

There are a number of lessons that can be gleaned from both experiences:

1.  Pain is part of the learning process.

2.  Do not allow previous knowledge to act as a crutch in the learning process.

3.  The best way to succeed is to embrace the challenge.

Continuing the story of my programming language education, a few years after I learned C, I desired to learn about object-oriented programming so I began reading books about C++ and writing OO code.  The learning process began anew but this time it was coupled with a new problem: when, where, and how should I apply OO techniques to the problems that I was solving.  This proved much more difficult than just absorbing OO syntax or semantics.  In fact, it took a number of years to get a good grasp on this problem.  The solution involved several important parts: learn from the best minds (read good code and books, discuss with experts), practice, and experiment.

Of course, I was not alone in my quest to understand OO.  The mainstream programming community was introduced to it in the 80s and really bought into it in the 90s.  Quite a few people get it somewhat, some people have no clue (think thinly veiled procedural programs in OO clothing or a clutter of design patterns where there is barely a need), and a few people really get it right.  I personally think that OO is especially hard to get since there is a dearth of good literature on the subject.  Only a few books stand out as generally accepted, Design Patterns and Refactoring come to mind, but even these books are criticized by many.

More recently there has been a trend towards programming languages incorporating functional language features in the language.  This has been happening for some time (procedures, recursion, and more recently garbage collection), but it really has been hitting its stride in recent years (closures, lambdas, continuations, type inference, monad like patterns).  The problem is this is the first time that the mainstream programmer has been exposed to these concepts.  How is she supposed to learn how to use these features?  How will it impact her work?  Are we in for the same process of maturation that OO programming experienced?  I think not.

Fortunately, there is a wealth of information about functional programming and a long history of experience.  This doesn't entirely free the would be functional programmer from the cost of learning a new way of thinking but it does drastically reduce the cost.  So how should a programmer learn to think functionally?  I recommend that a programmer read the best books, immerse himself in a functional language, and then practice, practice, practice.

The Best Books

Functional programming has been around since LISP which was the second programming language (following FORTRAN).  Whereas OO programming had its genesis in common sense modeling of the real world (simulation software), functional programming was born through theory (lambda calculus).  Academics have really embraced functional programming in research and so there are a number of very good books on functional programming.  Here are two of the best books on the subject.

1.  Structure and Interpretation of Computer Programs - Abelson and Sussman

2.  Introduction to Functional Programming 1st Edition - Bird and Wadler (Out of Print - maybe on Ebay?)

Read these books and enjoy drinking from the firehose.

Learning by Immersion

My second recommendation is to meet the challenge head on.  Learn a functional language like Lisp, Scheme, ML, Haskell, or Erlang.  It doesn't matter which language it is as long as it doesn't allow a regression to previous ways of thinking.  There will be a temptation at first to attempt a problem in ways that are comfortable and familiar, but working in a functional language will require a functional approach to the problem.  It is very analogous to my story of learning to climb hills on a bike.  I wanted to walk and at first it might well have been faster to walk but I forced myself to stay in saddle and in the end I could climb hills much faster on the bike than I ever could walking.  So stay in the saddle and learn to think functionally.

Practice

Once good literature and immersion have been used in the learning process, it will be natural to apply functional programming techniques to problems in a language that allows both functional and non-functional approaches to problem solving.  The final step is learning when to use the new tool in a mixed environment and the key to overcoming this challenge is to practice.  Experience is vital in any art because it tunes the senses to appreciate beautiful solutions.

C# 3.0 offers some features which can drastically improve the programming experience but only by learning to think functionally can they be fully appreciated.