Functional programming using JavaScript
In computer science, functional programming is a declarative programming paradigm based on the use of true mathematical functions. In this programming style, functions are first class citizens; functions expressions can be assigned to variables like any other value.
Functional programming is based on decomposing problems in small and reusable functions that take an input and returns a result. These functions don’t mutate or transform data.
With this structure we can compose more complex functions. These functions tend to be more concise, easier to debug and are more scalable.
Functions as first-class citizens
We say an entity is a first-class citizen when a given entity (like a function) supports all the operational properties inherent to other entities; properties such as being assigned to a variable, being sent as an argument of a function, being returned by another function etc.
In a nutshell, being a first-class citizen means “being able to do what everyone else can do”.
// Basic function in JavaScriptfunction sayHello() { return "Hello World";}
// Reference to a functionlet fn = sayHello;
// Function as a parameterfunction greet(fnMessage) { console.log(fnMessage());}
// Function as an argumentgreet(sayHello);
// Function as a resultfunction sayHello2() { return function () { return "Hello Again"; };}
High Order Functions
High order functions are functions that operate in other functions, either by using them as an argument or returning them as a result.
// map is a high order functionlet numbers = [1, 2, 3];numbers.map((number) => number * 2);
Function composition
Function composition is the process of combining two or more functions to produce a new function. You can think of these functions as pipes that our data will pass through.
The composition of a function f and a function g can be defined as f(g(x)).
// Simple solutionlet input = 10;let output = "'" + (input * 2).toString() + "'";console.log("output :>> ", output);
// Using functional programmingconst multiply = (num) => num * 2;const wrap = (str) => `'${str}'`;const result = wrap(multiply(input).toString());console.log("output :>> ", result);
Currying
Currying is a functional programming technique in which we can transform a function with multiple arguments in a sequence of nested functions. This sequence returns a function that expects the next argument in line. This process continues until all arguments are used and are been executed in the final function.
Let's see the following function that adds two numbers.
// Simple solutionfunction add(a, b) { return a + b;}console.log("output :>> ", add(2, 2)); // 4
// Using Curryingfunction add2(a) { return function (b) { return a + b; };}console.log("output :>> ", add2(2)(2)); // 4
// Currying with arrow functionsconst add3 = (a) => (b) => a + b;console.log("output :>> ", add3(2)(2)); // 4
Pure functions
Pure functions are functions that receive an argument and return a result without modifying any data out of his scope; in other words, they are functions without side effects.
The output value depends only in its input value. A pure function must always return a value.
Pros:
- They are self-documented functions
- Makes testing easier.
- Can be executed in concurrency.
- The output can be stored in cache.
Cons:
- They can’t use random values.
- They can’t use the current date/time.
- They can’t change the global state.
- They can't modify their parameters.
Immutability
We say something is immutable when it can't be modified. In the context of programming, a variable is immutable when its value can’t be modified. And an object is immutable when its state cannot be updated after its creation.
Immutability is a way to reassure out object doesn't get updated in unexpected places.
When using const in JavaScript we are not creating an immutable object, we are creating an object that cannot be reassigned.