Who am I?
I am a programmer who’s dreaming of functional programming as the next best thing. I no longer believe in object-orientation, which feels like loosing my religion.
I’ve been acquaintances with functional programming since a long time (does anybody know Clean, the programming language?); I’ve also been some FP conferences like CEFP 2009 and CEFP 2011, which left me with some nice memories and ideas. Unfortunately, the IT industry in my home city, Cluj, is shaped by outsourcing, so when I started working after finishing my studies, I could only choose between Java and C#; I finally chose Java, which was at version 6 at the time.
Java always felt to me, since the very beginning, like a simple, outdated language lagging behind the industry. I’ve always liked C# more, as it felt like a much more modern language: had support for lambdas since 2007 – Java has them only since 2014; had support for properties since the very beginning (2002), Java still doesn’t have it (and IMO will probably never have).
What’s wrong with Object-Oriented Programming?
Entire blog posts would not be enough to cover this topic in detail. To sum it up: OOP, as it’s practiced in Java, C++ and other mainstream languages, goes hand in hand with some bad ideas, most importantly with mutability and side effects. In these languages, immutability is considered an optimization to simplify certain things (such as Java only has immutable strings, or that literals are immutable, unlike in Fortran). Functional programmers argue that it’s immutability that should be the default, and mutability the optimization (for performance). Side effects should also be eliminated or controlled (called just effects). Why? Because these approaches make reasoning about our code easier, leading to fewer bugs and to a better overall design.
The famous Gang of Four Design Patterns are mostly based on mutability and side effects (can you imagine the observer pattern otherwise?) They also try to fix limitations of the language (command and strategy are equivalent to first-class functions). I’ve found that this stackoverflow answer does a pretty good job at explaining this.
OOP also has some pretty basic limitations, such are you are unable to express the current type when in a hierarchy.
Why Functional Programming?
Functional programming incorporates some nice ideas, including the ones below.
- think in terms functions that take some input and produce some output; they don’t do more than that (have no side effects). This is like encapsulation on the code: in order to understand what a function does, it’s usually enough to just read its name, input type and output type, leading to few surprises. Functions, together with a great type system (such as Haskell’s or Scala’s), can really help you communicate the intent of a function.
- lack of mutability and side effects reduces the number of moving parts, helping better reasoning about code, leading to less bugs, better testability, leading to better design (such as the Elm Architecture), and helps you being happier overall.
- better parallelism: immutable data doesn’t need locking, side-effect free functions can be executed at any time, on any thread, or on any machine, providing a lot of freedom for an optimizer to do its job, actually giving you better performance.
- you can code like you played Lego, doing composition: build your program out of little programs that are themselves built of even more little programs and so on. Functions are known to be compositional. Side effects do not compose.
- … and many more.
Why hasn’t functional programming gone mainstream decades ago, when it was first introduced?
First, our computers grew significantly better, and memory is no longer a serious limit (hence the widespread garbage collection). Functional programming loves memory and absolutely requires garbage collection.
More importantly, while the memory sizes (both RAM an HDD/SSD) keep increasing exponentially according to Moore’s law, the CPU power / unit of execution no longer does so; in order to keep up with the increasing demand, we can use multi-core CPUs or simply do horizontal scaling and use a lot of individual machines. The problem is how to efficiently use the concurrent computing ability of our hardware. The traditional, imperative programming is inherently sequential.
The standard way of doing concurrency in Java, C# and many more, is to use multiple threads, and to share your mutable data between them, protected by locks. That’s often referred as the synchronization quadrant and is infamously difficult to get right.
The purely functional programming language Haskell has pretty good support parallelism, including implicit parallelism (ideally, the runtime should figure it out for you, but we’re not there yet, so you need to place some hints).
The only constant in the IT world is change. Our programming languages are no different. Java needs to evolve in a much grater pace if it wants to keep up. New programming languages are born influenced by functional programming (Kotlin, Swift), or some fully embrace it (Elm, PureScript, Eta). Some frameworks require you to think functionally (Spark, Storm, Reactive Extensions).
Functional programming is the new trend nowadays. I believe in it, as I’ve felt its benefits on my skin numerous times; craved its practices constantly when working with Java 6/7 and even including 8; felt like I’ve arrived home when working in Scala or Haskell.