A programming paradigm is a way of thinking about software construction based on a few defining principles. Functional programming is one such paradigm which is composed of pure functions and which avoids shared state, mutable data, and side effects. Functional programming is declarative rather than imperative, and in contrast to object oriented programming, application state flows through pure functions.
Functional code tends to be more concise, more predictable, and simpler to test than imperative code but can have a steep learning curve so it can be intimidating to learn. I hope that this article clears some things up for you and provides a fundamental understanding of functional programming and its benefits. To begin understanding what functional programming is, you have to start with understanding some of the core concepts.
The first fundamental concept to learn is pure functions. Pure functions are essential for a variety of purposes, including reliable concurrency, React and Redux apps, and functional programming. Let’s go over what makes a function “pure”:
- A pure function, given the same inputs, always returns the same output
- A pure function has no side effects (more on that later)
Pure functions are completely independent of outside state so they are immune to many bugs that have to do with shared, mutable state. This independence also makes pure functions extremely easy to move around, refactor, and reorganize in code, making your programs more adaptable to future changes.
Shared state is any variable, object, or memory space that exists in a shared scope or as the property of an object being passed between scopes. The problem with shared state is that in order to understand the effects of a function, you have to know the entire history of every shared variable that the function uses or affects. A second problem associated with shared state is that changing the order in which functions are called can cause a line of failures.
Functional programming avoids shared state, instead relying on immutable data structures and pure calculations to derive new data from existing data.
As a reminder, an immutable object is an object that can’t be modified after its creation. If you want to change an immutable object, the next best thing is to create a new object with the new value. Immutability is a central concept of functional programming because without it, state history is lost and bugs can creep into your software.
A side effect is any application state change that is observable outside the called function other than its return value. Examples of side effects:
- Modifying any external variable or object property
- Logging to the console
- Writing to a file
Functional programming avoids side effects which makes your software easier to extend, refactor, debug, test, and maintain.
Functional programming is a declarative paradigm, meaning that the program logic is expressed without explicitly describing the flow control. Where imperative code usually relies on statements, pieces of code that perform some action, declarative code utilizes expressions, code which evaluates to some value through some combination of function calls, values, and operators. In other words, declarative programs abstract the flow control process and focus on the data flow: what to do; the how gets abstracted away.
Functional programming favors pure functions instead of shared state and side effects, immutability over mutable data, and function composition over imperative flow control. Functional programming is often easier to understand because it doesn't change state and depends only on the provided input. For similar reasons it is also easier to test and debug a declarative program.
For further reading on this topic, check out some of these sources:
- Functional Programming Paradigm by Vishalxviii of GeeksforGeeks