0%

javascript-functional-programming

What is functional programming?

Functional programming is a programming paradigm that treats computation as the evaluation of mathematical functions and avoids changing state and mutable data.

Functional programming concepts

Pure functions

A function is called pure function if it returns the same result for the same arguments and has no side effects.

And here is the full definition of a pure function from WikiPedia

In computer programming, a pure function is a function that has the following properties

the function return values are identical for identical arguments (no variation with local static variables, non-local variables, mutable reference arguments or input streams, i.e., referential transparency), and
the function has no side effects (no mutation of local static variables, non-local variables, mutable reference arguments or input/output streams).

pure function

1
2
3
function add(a, b) {
return a + b;
}

non-pure function

In the following example, the calculateTax function depends on the external variable taxRate. This means that if taxRate changes, the output of calculateTax changes even if the input remains the same. Therefore, calculateTax is not a pure function.

1
2
3
4
const taxRate = 0.1;
function calculateTax(amount) {
return amount * taxRate;
}

Is the following function pure?

1
2
3
function mergeArray(arr1, arr2) {
return arr1.push(...arr2);
}

No, the function mergeArray is not pure because it modifies the arr1 array in place using the push method.

How to make the mergeArray function pure?

1
2
3
function mergeArray(arr1, arr2) {
return [...arr1, ...arr2];
}

Immutable data

In functional programming, data is immutable, which means it cannot be changed once it’s created. Instead of modifying existing data, we create new data with the desired changes.

Side effects

A function is said to have a side effect if it modifies some state or variable outside its scope.

1
2
3
4
5
6
7
8
let count = 0;

function incrementCount() {
count += 1;
}

incrementCount();
console.log(count); // Outputs: 1

In this example, the function incrementCount has a side effect because it modifies the global variable count. This is a side effect because it’s changing state outside of its own scope.

Referential transparency

A function is called referentially transparent if it can be replaced with its value without changing the program’s behavior.

1
2
3
4
function add(a, b) {
return a + b;
}
console.log(add(2, 3)); // Outputs: 5

In this example, the function add is referentially transparent because we can replace add(2, 3) with 5 without changing the program’s behavior.

First-class functions

In JavaScript, functions are first-class citizens. It means we can assign functions to variables, pass functions as arguments to other functions, and return functions from other functions.

function as variable

1
2
3
4
5
const add = function(a, b) {
return a + b;
};

console.log(add(2, 3)); // Outputs: 5

function as argument

1
2
3
4
5
6
7
8
const nums = [1, 2, 3, 4, 5];

function isEven(num) {
return num % 2 === 0;
}

const evens = nums.filter(isEven);
console.log(evens);

function as return value

1
2
3
4
5
6
7
8
function createGreeter() {
return function(name) {
return `Hello, ${name}!`;
};
}

const greet = createGreeter();
console.log(greet('John'));

Higher-order functions

A function that takes one or more functions as arguments or returns a function is called a higher-order function.
There are many functions in javascript that are higher-order functions, such as map, filter, reduce, forEach, sort, etc.

declarative vs imperative

Declarative programming is a programming paradigm that expresses the logic of a computation without describing its control flow. In contrast, imperative programming is a programming paradigm that uses statements that change a program’s state.

Example:
Given an array of numbers, multiply all even numbers by 10 and return the sum of them.

Imperative way:

1
2
3
4
5
6
7
8
9
10
const numbers = [1, 2, 3, 4, 5, 6];

let sum = 0;
for (let i = 0; i < numbers.length; i++) {
if (numbers[i] % 2 === 0) {
sum += numbers[i] * 10;
}
}

console.log(sum); // 60

Declarative way:

1
2
3
4
5
6
7
8
const numbers = [1, 2, 3, 4, 5, 6];

const sum = numbers
.filter(num => num % 2 === 0)
.map(num => num * 10)
.reduce((acc, num) => acc + num, 0);

console.log(sum); // 60

Benefits of functional programming

  • Easy to test
  • Easy to run in parallel(concurrency)
  • Easy to cache

References

Wikipedia