Why Functional Programming?

Akash Yadav
CodeX
Published in
4 min readOct 17, 2021

Let’s start by taking an example :

Imperative Style
Declarative Style

We have 2 programs for printing odd numbers to the console. The difference between these programming paradigms is the nature of how we read and write code. These two paradigms are Imperative and Declarative.

Imperative :

  • Imperative code means code that is focused primarily on HOW to do something in terms of instructions/procedures. Due to the HOW nature of this style, our brains need to mentally execute the code before we understand its purpose. We simply can’t glance at the code and immediately understand what the particular piece of code is doing.

Declarative :

  • In Declarative style HOW is not important, what matters is WHAT. In this style, the program specifies WHAT needs to be done in terms of expressions. Functional Programming is by its very nature is more declarative.

There is no exact checkmark of what code is declarative or imperative. It’s relative. If you are doing low-level programming using assembly languages or coding directly in 0 or 1 Haha, and then if you see a for loop or if statement, you’ll say wow that’s so declarative and then if you compare it with some functional style the same code will start looking as imperative. It’s all about the level of abstraction we are at.

If we write some code that forces the person to mentally execute the code in their head just so that they can understand it, is a code that is harder to understand, to maintain, to improve, to fix. So the goal is to shift the focus of the reader of our code, towards the declarative nature away from imperative nature, so that it is easy to understand.

What is Functional Programming?

In the functional programming paradigm, we construct our programs using only pure functions. In order for a function to be pure, it should be Referentially transparent. I will explain what referential transparent means in some time, but first, we will understand what is the actual definition of a function in the spirit of functional programming.

What’s a pure function?

In the spirit of functional programming, a proper definition of pure function is

  • A function not only takes some input, but it also has to return some output. The below example does not qualify for a function as it does not return any output instead it is causing side-effects by printing to the console.
  • A function would be better if the function name can describe the semantic relationship b/w the input and output.
f(r) = π * r * rIn the above example, areaOfCircle perfectly describe the semantic relationship b/w function input and output.
  • In a function, input and outputs should be direct. A function call should do its business in isolation from the rest of the program. It should not cause any side effects. In the below example, both inputs and output are indirect and getting changes over the course of the execution of the program.
  • A function can have indirect inputs as long as they are not mutating or changing. Indirect inputs should be constant throughout the course of the program. Here pi is never changing, therefore variable pi as an indirect input is valid.
  • A function call should return the same output over the same input any number of times when called

In the below code example, both areaOfCircle and areaOfCylinder function call is referentially transparent as we can literally replace the function call for the same input with the computed value, without affecting any of the rest of the program.

Due, too referential transparency we are guaranteed on the output of the function call, therefore language compilers can take advantage of it and memoize the result of the function call for a given input and literally replace its value everywhere not to compute the same value again. It’s just like solving the inner expression and substituting its result to now solve the bigger expression, and so on and so forth.

This also gives an advantage to the reader of the code, and if we can also do the same substitution in order to quickly understand and get the result and solve the expression.

I’ve also used the term side-effects in my explanation. So what are they?

Side-effects are nothing but which reflect change or mutability. Examples of side effects are :

  • Any sort of I/O operations
  • Network calls
  • Database writes
  • TimeStamp generation
  • Value mutability, for example, mutating a data structure i.e pushing to an array or popping from it.

So in order to prevent value mutability, we create a new clone instead of modifying it, with the changes in effect. You might be thinking that this can cause CPU and Memory overhead as we will be copying the same data over and over again, that’s where we get the help from Immutable data structure libraries such as Immutable.js and Google Guava. They abstract these things out from our business logic context and takes care of this in a more performant way. More on How they do it in a different blog.

It’s impossible to have a practical program without having any side effects. So the question is not to have 0 side effects, it is to minimize side effects, either by containing it in local scope or extracting it and placing it where it is commonly known. Minimizing these side effects will have us debug faster and will help us where to look for the bugs in the future as bugs are more likely to happen where there are side-effects and mutation of the state is happening.

Hope this blog will help you in understanding the reason behind functional programming. There is much more to functional programming, i.e partial application, currying, function composition. More on this later. See yaa !!.

--

--