Functional Programming Concepts

GID Master
7 min readMar 19, 2021

Functional Programming Concepts show a way to develop application composing functions without any side effects and that except the same response. The idea is send parameters through pure functions and always expected the same response.

Ensuring that the data is only changing when you want it to change, it helps developers to reduce what they need to keep in mental map of the application, using imperative structure it should define not only what it should do but also how it should be done.

Programming Paradigm

Most common paradigms are Procedural and Object-oriented programming (OOP) which define how the application is architected.

However, functional programming would be more similar to object-oriented programming, considered part of a larger paradigm that tries to bind all the logic in pure logical functions.

Procedural

Program uses procedures to call the functions that perform a sequence of steps. So any function can be called from anywhere and change the state of data from any point of your application.

Object-Oriented Programming (OOP)

Program uses objects to call functions that belong to a specific type of object grouping special properties and methods.

Declarative and Imperative

Let’s compare these concepts using a practical and common scenario.
Imagine a simple object containing all tasks of a project and we want to get only pending tasks.

Imperative

Imperative cares more how to perform an action and change the state of your application, it’s a bad practice for developing functional programming concepts.

A simple example of imperative, probably you have already seen a loop like this one somewhere. A loop that reserves all data that we need into an external array, a classic example of side effect.

//get only pending tasks
let pendingTasks = [];

for(let i=0; i<tasks.length; i++){
if(!tasks[i].completed){
pendingTasks.push(tasks[i]);
}
}

Declarative

Concept of telling to function what you want instead of telling how to process, it’s a good practice for developing functional programming concepts.

//get only pending tasks
const pendingTasks = tasks.filter(t=> !t.completed);

Both functions do the same thing and achieve pretty much the same result, but using declarative functions make developers worry less about the details of how it works. It means we can focus more on the fact of doing the work.

Pure x Impure Functions

In functional programming a function is considerably a simple mathematical function. In other words, all the time you call a function with the same parameters you should get the same result.

It is important to consider function with no side effects.
So If it modifies some state outside its scope, then your function logic becomes useless because you have no idea what it will produce as response even if you use the same parameters.

Pure Functions

All functions should have only their own arguments processed, don’t use external variables or external functions, it shouldn’t change the state of the data or create an external dependency.

Function always should return something, so whatever inputs should be used to process and output a value.

add(value1, value2) => { 
return value1 + value2;
}

Impure Functions

It is pretty much the contrast of pure function where developers create external references and mutate state.

Most of the time even passing the same arguments, the function can return different results because it depends on external factors and states.

let value3 = 20;
add(value1, value2) => {
return value1 + value2 + value3;
}

Immutable

The concept that data cannot be changed once it is created is very important in functional programming.

For the simple reason that makes clear and easier to see what is causing the data to change, and have the confidence that it has not been changed behind the scenes.

Instead of changing the data, we always create a new instance of the data with the updated values before using it.

Immutability is very important and useful for performance, once the stored value is changed it takes awhile to JavaScript recognise that the property was changed.

Basically every simple property in the object should be checked to activate the change detection. However, using immutability JavaScript just check if that object reference was changed.

Mutable Data

//we change the status of the tasks directly inside the object
for(let i=0; i<tasks.length; i++){
if(tasks[i].completed){
tasks[i].status = "COMPLETED";
}
}

Immutable Data

//we create another object reference before manipulate the data
const taskCompleted = tasks.map(obj => {
obj.status = (obj.completed) ? "COMPLETED" : obj.status;
return obj;
});
//easy way to clone a simple object without child references
const clone = Object.assign({}, tasks);
// if the object has multiple references
// then we can use stringify the json
const clone = JSON.parse(JSON.stringify(tasks));

Currying

Currying is the concept of breaking down a function that accepts multiple arguments into a series of functions that use these arguments.

It is a lot used to format some data, we pass as argument the object itself and keep it dynamic enough to be used in different situations.

Examples of how to use currying:

//filter the tasks using keys/values 
const filterTasks = (key, value, data) => {
data.filter(obj => obj[key] == value);
}
//filter tasks completed or not
const isTasksCompleted = (state, array) => filterTasks('completed', state, data);
//get only completed tasks
const completed = data => isTasksCompleted(true, data);
//get all pending tasks
const pending = data => isTasksCompleted(false, data);
//picture an object containing all tasks
const tasks = { ... }
completed(tasks);
pending(tasks);

Currying x Partial Application

All currying is a partial application, but not all partial applications are currying, partial applications execute functions with less parameters that it is expecting.

It doesn’t mean that should take just one parameter, we can hardcode values inside the function to help to manipulate the output.

However, currying takes multiple parameters and returns a function with exactly one parameter.

//currying
add(value1, value2) => {
return value1 + value2;
}
//partial application
add2(value1) => {
return value1 + 2;
}

Closure

Talking about lexical scope, it is a persistent local variable.

In functional programming we need to make sure that all variables created in that specific scope should be accessed only there, even calling these functions outside of the scope the data persisted should be returned.

In the block of code given above we should wrap all the variables in a function scope called tasks, then we will be able to access tasks variables from other contexts, inside project context for example.

//create a pure function simulating pipe behaviour
const pipe = (f, g) => (...args) => g(f(...args))
//all tasks completed
const tasksCompleted = (data) => data.filter(obj => obj.completed)
//all tasks completed today
const tasksCompletedToday = (data) => data.filter(obj => obj.dateCompleted == Date.now())
//filter tasks completed today using pipe composing functions
const tasksDaily = pipe(tasksCompleted , tasksCompletedToday )
//picture a collection of tasks
const tasks = { ... }
tasksDaily(tasks)

Higher-Order Functions

This term sounds really complicated, actually it is a simple part of functional programming concepts.

Higher-Order functions are functions that either take a function as a parameter or returns a function as a result, the idea is to abstract many actions that we can from a logical function.

The function pipe created above is a good example of higher-order function, ES6 has map and filter are also other good examples.

Compose

Composition is putting together functions to deliver the output that you need.

Functions are built using blocks approach.
Imagine a process or machine and each function is a piece of it, so when we run the machine supplying the inputs then we get the predictable results.

The idea is having individual functions that alone don’t mean much, but when they are put together they define the logic of your program.

One of the biggest examples of using compose is the famous pipe available in a few libraries where we provide a sequence of manipulation to get a final object.

RxJs is a powerful library to deal with reactive programming, and pipe is the main thing when you use this library.

Conclusion

There are plenty of libraries out there that you can use to help you to speed the development using auxiliary functions to deal with most of functional programming.

Lodash is my favourite one, really powerful lib and well documented to manipulate array in many different ways. Sanctuary, Folktale, Monet.js, Ramda and ImmutableJs are other pretty common libs.

It doesn’t matter the libraries that you will be using, as long as you understand the concept and all benefits of implementing functional programming.

ES6 is so powerful that you can pretty much create your own pure functions without any third-party help.

--

--

GID Master

Web Architect — Full Stack Developer — Mobile Web Specialist