Its 1992, I’ve got a full head of hair, a ‘Stussy’ T-Shirt I practically live in and I’m staring at the whiteboard where my lecturer seems to be writing up an endless sea of brackets interspersed with the odd keyword. The topic is programming in LISP, and despite my best efforts I’d rather be listening to a lecture on OOPs, or hitting the gym, or hitting the pub...
Twenty-six years later, my hair has all but gone, and I’m talking to a technologist about why one of my clients is using Clojure versus Haskell. Bringing this language to life in a commercial context I can say I now get the power of functional programming.
I spent my software engineering career building solutions in a variety of languages, but never functional. A long career in tech has taught me never to try and win a public debate over which language, paradigm or methodology is better than another so I’ll not try it here. Instead I’ll share with you the same overview I shared with the team as we explored the differences between object orientated programming versus functional programming.
Essentially this comes down to different programming paradigms and how you as a programmer want to design and implement your solution. Programming at its heart is really about data and behaviours that act on that data.
In an object orientated world, you define your approach by designing objects which represent both a set of data and the behaviours that can act on that data. Most OO languages will talk about:
- Encapsulation – a means of combining data and functions together into an object. This helps prevent unwanted access to the data directly
- Inheritance – a means of re-using the data and functions of another object
- Polymorphism – a means of changing the behaviour of a function based on the type of the data its acting on
Advocates would argue this approach has many advantages including that software is easier to read and understand because of its modular design and its quicker & cheaper to build applications because of the ability to re-use objects.
A functional paradigm on the other hands takes a very different approach and strongly segregates the data from the behaviours. Generally speaking, functional languages support the following:
- Immutability – meaning data cannot be changed, only new versions of the data can be created
- Pure functions – meaning a function always returns the same result for the same input and that it has no side effects in that it doesn’t change any other data. Consequently, functions tend to be small and very tightly defined
- Functions as parameters and return values – meaning functions can take other functions as parameters and the return results can also be functions.
Advocates of functional programming would argue this gives multiple advantages: -
- Programs are easier to maintain and extend as the code is simpler to understand at a high level without the need to delve into the details of each function because you can be more confident that the functions aren’t hiding complex logic or changing state
- Functions are easier to test because of their discrete nature and that they do not modify data unexpectedly
- Concurrent programming is safer because data is immutable, so you don’t need to be as concerned about race conditions or multi-threading issues
What’s interesting is that many traditionally object-oriented languages have started to introduce features or libraries associated with functional programming giving the programmer the ability to flex their approach depending on the problem they are trying to solve.
What’s clear is that both new and existing languages will continue to evolve and leverage the best features of the languages of those before them while giving the programmer the flexibility to adjust the style dependent on the problem they are solving.
With Functional Programming first coming into being in the 1960s its clear its strengths are born out through its longevity.
Gary Rawlings is our in house tech expert and a key member of our senior leadership team.