It’s surprisingly hard to find a consistent definition of functional programming. But I think you can define FP with just two statements:
1. FP is about writing software applications using only pure functions.
2. When writing FP code you only use immutable values.
Hence, Functional programming is a way of writing software applications using only pure functions and immutable values.
Now, let us understand the two statements that we stated above.
A pure function can be defined like this:
- The output of a pure function depends only on
(a) its input parameters and
(b) its internal algorithm,
which is unlike an OOP method, which can depend on other fields in the same class as the method.
- A pure function has no side effects, i.e., that it does not read anything from the outside world or write anything to the outside world. – For example, It does not read from a file, web service, UI, or database, and does not write anything either.
- As a result of those first two statements, if a pure function is called with an input parameter x an infinite number of times, it will always return the same result y. – For instance, any time a “string length” function is called with the string “Ayush”, the result will always be 5.
- Example of Pure function
The best FP code is like algebra, and in algebra you never reuse variables. And by avoiding the re-use of variables we can get the benefits like,
- You can always rely on a value to replace it with some functionality, for instance, you have val a = f(x).
Here you can always use the value a as a replacement for f(x), as its value can’t be changed, which is not the case with var a = f(x). Hence, the algebraic substitutions are possible.
- Here, a and b can never change, the code is easier to reason about. With var fields you always need to have a background thread running in your mind, “Is a reassigned somewhere else? Keep an eye out for it.”
- Another reason to use only immutable values is that mutable variables ( var fields) don’t work well with parallel/concurrent applications. The reason for this being that concurrency is becoming more important as CPUs use more cores.
Benefits of Functional Programming
- Pure functions are easier to reason about :
You know that they can’t do certain things, such as talk to the outside world, have hidden inputs, or modify the hidden state. Because of this, you’re guaranteed that their function signatures tell you 2 things :
(a) exactly what’s going into each function,
(b) coming out of each function.
- Testing is easier, and pure functions lend themselves well to techniques like property-based testing:
It’s easier to test pure functions because you don’t have to worry about them dealing with hidden state and side effects.
- Debugging is easier:
Because pure functions depend only on their input parameters to produce their output, debugging applications written with pure functions is easier. You don’t have to worry about what’s going on in the rest of the application, you just have to know the inputs that were given to the pure function that failed.
- Programs are more bulletproof:
There are fewer “moving parts” — mutable variables and hidden state — in FP applications, mathematically speaking, the overall application is less complex.
- Pure Function signatures are more meaningful:
Non-FP methods can have side effects i.e., hidden inputs and outputs of those methods, ultimately their function signatures often don’t mean that much.
It takes no input parameters and returns nothing, there’s no way to guess from the signature what this method does. In contrast, because pure functions depend only on their input parameters to produce their output, their function signatures are extremely meaningful.
- Parallel/concurrent programming is easier:
A functional program is ready for concurrency without any further modifications. You never have to worry about deadlocks and race conditions because you don’t need to use locks. No piece of data in a functional program is modified twice by the same thread, let alone by two different threads. That means you can easily add threads without ever giving conventional problems that plague concurrency applications a second thought.
Disadvantages of Functional Programming
There are a few disadvantages of FP as well but don’t worry, there is a way around to every problem.
- Writing pure functions is easy, but combining them into a complete application is where things get hard:
All of the functions follow the same pattern:
1. Data in
2. Apply an algorithm (to transform the data)
3. Data out
Gluing pure functions together to create a complete FP application is one of the biggest stumbling blocks you’ll encounter. But there are solutions for this which ultimately is a topic for another day.
- Advanced maths terminologies makes FP intimidating:
When you first hear terms like combinator, monoid, monad and functor, you feel these terminologies intimidating and that fear factor becomes a barrier to learning FP.
- For many people, recursion doesn’t feel natural:
For many programmers coming from OOPs paradigm, recursion is a familiar thing but quite often that familiarity level goes begging initially. Due to immutable values, the only way to loop over elements is to use recursion. But once comfortable, it is much more interesting to write codes using recursion.
- Because you can’t mutate existing data, you instead use a pattern that I call,“Update as you copy”:
It is quite easy to mutate existing data in Non-FP but in FP what you do is :
(a) Copy an existing object to a new object, and then as a copy of the data is flowing from the old object to the new object,
(b) Update any fields you want to change by providing new values for those fields.
- Pure functions and I/O don’t really mix.
- Using only immutable values and recursion can lead to performance problems, including RAM use and speed:
But this can be reduced to a great extent by the use of tail recursion.
FP paradigm is not a replacement of OOP, but definitely worth learning as it provides an amazing bunch of features as we have discussed above. It is quite hard to decide the side to choose in the battle between FP and OOP, but we can surely say that FP certainly holds the upper hand when it comes to concurrency/parallelism, lots of maths, etc.
I hope now you have a fair idea about FP and quite ready to explore out the FP paradigm.
- Learning FP in Scala By Alvin Alexander