Functional style programming focuses on pure math functions, immutable data, logic flow, and strong data typing. Functional programming languages are the opposite of object-oriented ones, which focuses on mutable data and changeable states.
Functional programming languages are everywhere, and the vast majority of the internet uses them. In fact, I’m using a functional programming language right now to type this article.
Learning what a functional programming language is and knowing its advantages and disadvantages is useful for anyone entering into a field in computers or programming.
Let’s take a moment to define this programming paradigm (and paradigms in general) and then look at some of the pros and cons of functional programming.
What is a Programming Paradigm?
Since computers are, at their core, machines, we need a good way to communicate with them. However, the more abstracted from ones and zeros that we get, the more specialized a language becomes. This is why we have so many high-level languages, because they all function a little differently and are all well suited for different tasks.
Enter the programming paradigm, which is a way to categorize programming languages by their central theory or methodology for handling data. Languages qualify for a paradigm by having a number of defining principles. There are many programming paradigms, many of which overlap or contain other paradigms. The two major paradigms are functional and object- oriented, but there are plenty more ways of handling data not considered by these two paradigms.
What is Functional Programming?
Functional programming is one of the two most well-known programming paradigms, with object-oriented programming being the other. In short, functional programming focuses on pure mathematical functions and immutable data, which is data that cannot be changed after it’s created. It doesn’t have state, which means that the only thing that changes in a functional program is the input.
Because there are no changing states with objects, in functional programming you could conceptually change around the order of the code and still have the same output. It’s as if you were multiplying eight numbers together, it wouldn’t matter what order you multiply them in, you would still achieve the same result.
In this sense, functional programming is all about flow. Inputs come in the top and results fall out of the bottom. This contrasts with object-oriented programming, which is more of a changing state machine, with unique and mutable objects.
Functional programming falls under the imperative programming paradigm umbrella, the opposite of declarative programming where object-oriented programming resides.
Defining Principles of Functional Programming
Functional programming rests on a few defining principles, which all languages that subscribe to this methodology rest on as well. They are:
- Pure Functions – Functional programming uses pure functions. These are functions that do not change, produce reliable results, and always produce the same result for the same input. They do not produce unexpected results or side effects and are absolutely predictable, regardless of outside code.
- Immutability – This is the principle that once you set a value for something, that value won’t change. This eliminates side effects or unexpected results because the program isn’t reliant on state. Thus, functions always work the same way every time they are run; they are pure functions.
- Disciplined State – New values can be created, so there are some states that can change in that sense, but it’s a deeply controlled process. Functional programming strives to avoid shared state and mutability. If the state is tightly controlled, it’s easier to scale and debug, and you get less unexpected results if something mutable changes in a way that is unexpected.
- Referential Transparency – This principle comes from a combination of pure functions and immutability. Because our functions are pure and predictable, we can use them to replace variables, and therefore reduce the number of assignments we make. If the result of a function would equal a variable, since our results are predictable, we can just replace the variable with that function.
- First Class Functions – This principle is simple. Functional programming values certain functions, first class functions, very highly. Therefore it has support to pass whole functions between itself as easily as other languages might with variables. These functions can be treated like values or data in functional programming.
- Type Systems – Since functional programming is so focused on precision and preventing errors, having a statically typed system makes sense. This is to make sure that every data type is assigned correctly, strings are strings and floats are floats, and prevents you from using unpredictable variables. This helps out our pure, error-free functions that may require a certain data type to work properly.
Functional Programming Pros and Cons
As with all programming paradigms, functional programming has its advantages and disadvantages. Let’s take a look at them to figure out our best use case for functional programming.
- Readability – Because we’ve kept almost everything to a function level, our code is easy to read. What you see is what you get, the states don’t change unexpectedly, and most of the data is immutable. There is no need to search for what is controlling our variables, or throwing out an odd error, or changing our code from other functions. All of our code is in front of us with functional programming.
- Stability – Because we’ve so strictly controlled our code there are no loose ends, no wild or errant variables, and no side effects. Everything tends to happen as planned because that is how the code is designed. Rather than being an unpredictable state machine that has too many moving parts to keep track of or fully understand, functional programming is more like static objects data bounces off as it makes its way downstream.
- Easier to build – Because functional programming is so stable it’s easy to keep building on it, trusting that your foundation is secure. It’s also easier to achieve high levels of abstraction, with functions on functions, that allows you to neatly tuck away most of your more routine code, like iterative programs and code, and makes for shorter and more stable code.
- Easier to debug – Because the code is readable, the flow of data has a clear path through the code, and our functions are holy and pure, debugging is a lot easier. You will spend less time chasing down errant bugs, side effects, and unpredictable states if there are no states or mutability.
- Focus on what, not how – Functional programming falls under the declarative umbrella paradigm, which means the focus when programming is on what you want to happen, while functions will take care of the how.
- Less readable – For some of the same reasons functional programming can be easily read, it can also be difficult to read. Many of the features in functional programming can be easily abused to create teetering towers of abstraction, where a short line can contain volumes and one must dig through piles of functions to find what it really does.
- Hard to learn – Functional programming is more academic and strict than object-oriented programming. It also requires a better understanding of algebra, lambda calculus, and category theory, which it relies on heavily. There are less accessible learning materials for functional programming, and functional programming requires a different kind of logic than we are typically used to.
- Hard to use – Upholding the above principles is difficult, especially when having mutable states makes programming so much easier. Functional programming often makes you take the long way around, so while writing an individual function is easy, creating a complete program is difficult.
- Performance – Using a lot of immutable values means using more memory or more processing power, because to change a value one must either create a new piece of information or run a function to get the result every time it’s called.
- Input/Output – IO relies on side effects, which functional programming is designed to avoid. While IO can be integrated into functional programs, it goes against the flow by nature and requires special consideration.
Functional Programming Languages
Functional programming is a lot older than object-oriented programming, and it’s made a bit of a comeback in recent years. That comeback is mostly due to the languages on this list.
- Haskell – Haskell is another pure functional language, and it’s designed around solving real world problems, rather than academic ones. It’s not as old as Lisp; it was created in the 1990s. It’s been used for a few popular projects, like Xmonad window manager.
While functional programming fills a more particular spot over object-oriented languages, its rise in popularity means a demand for more functional programmers in a field where there are very few. Learning functional programming would put you in a unique job market, one that is rewarding and enjoyable in its own right.