Functional programming(FP) is a way of writing software applications using only pure functions and immutable values. Or Let’s say FP is a mathematical oriented way to write code. So, what do I mean by Pure Functions?
f(x) => x+1 ; This is a pure function as it will result in same output for the same input provided as many times as evaluated!
A pure function doesn’t change the state or change “the outside world” — the world outside of the function’s scope.
It cannot depend on any hidden state or global variables. The evaluation of the function should not cause any side effect, such as mutation of mutable objects or output to I/O devices or modify any fields outside of the function scope. And it does not modify its input parameters.
To sum up — Output depends only on Input + No Side Effects!
Now you may be asking, what are Side Effects? Let’s cover that later before let’s dig into “Why pure functions”??
- Easier to justify f(x) => x * x . You can just tell most of the things about a function looking at its signature.
- Easier to test and debug, pure function depends upon the input and the algorithm not on the parameters out the function scope(like global variables).
assert(pureFuncAgeAfter5years(25) == 30)
As you see in the above line, testing a pure Function is easy but on the other hand impure Function is dealing with a I/O, hence difficult to test. Let’s take another example of impure function. In the below code, function(calculateSum) is talking to the outside world parameters, hence becomes difficult to test as calling the same function twice, results in different outputs! i.e. 5 & 10, 5 being not equal to 10
- Easier to write Concurrent applications as stated-
“If there is no data dependency between two pure expressions, then their order can be reversed, or they can be performed in parallel and they cannot interfere with one another (in other terms, the evaluation of any pure expression is thread-safe).”
- Referentially transparent-
An expression is referentially transparent if it can be replaced with its value without changing the program’s behavior.
- Idempotent- For a give value ‘x’ it will produce the same result no matter how many times it is called!
It is safe to recompute the function any number of times.
- Lazy evaluation- The evaluation is postponed until the value is needed(called somewhere in the program). Sometimes it’s better optimization to eliminate things we otherwise don’t have to execute.
Side Effects can be bugs where concurrency and parallelism is needed! (That’s a pretty harsh statement)
- print(“Hello World”) : writes to the console immediately
- stdln.readLine(): reads the console immediately
- System.nanoTime(): Retrieve current time from the JVM immediately
- Future(deteleDb): Deletes the database immediately
Their results rely on some form of hidden I/O.
But in the programming world we cannot overlook writing to files, reading from databases or reading from console. A program would make no sense if it doesn’t talk to the outside world at some point of time! That’s where IO monads come into picture, Monads encapsulate side-effects and design more elegant programs. which I would be covering in the next part! But before that I would cover The need of Immutability in the world of FP.