Understanding pure functions in javascript

Understanding pure functions in javascript

Pure functions allow us to get a predictable result every time they are been invoked. They find its applications in redux, functional programming. Hence in order for a function to be classified as pure, it must fulfill certain rules:

1) Given the same arguments, it returns the same result: let us illustrate this

const sum = (a, b) => a + b 
sum(1, 3) // 4
sum(1, 3) // 4
sum(4, 2) // 6
sum(4, 2) // 6

looking at sum produces the same result, when we pass the same argument to it, sum satisfies the first rule of pure function.

2) Pure function does not produce side effects:- sides effects could be mutating external state, logging(e.g console.log), API request, I/O operations.

const sumWithLog = (a, b) => {
console.log(a, b)
return a+b
}

const arr = [2, 3, 4];
const addToArr = (arr, a) => { 
arr.push(a);
return arr;
}
console.log(addToArr(arr, 5)) // [2, 3, 4, 5];
console.log(addToArr(arr, 5)) // [2, 3, 4, 5, 5];

Looking at sumWithLog it technically violates the second rule by definition despite it obeys the first rule, while addToArr is not also a pure function because it's mutating external state. let's make impure addToArr to become pure by adjusting the code,

const arr = [2, 3, 4];
const addToArr = (arr, a) => {
const arrCopy = [...arr]  //  line 1
arrCopy.push(a);
return arrCopy;
}
console.log(arr) // [2, 3, 4] 
console.log(addToArr(arr, 5)) // [2, 3, 4, 5];
console.log(addToArr(arr, 5)) // [2, 3, 4, 5]
console.log(arr) // [2, 3, 4]

Looking at the code snippet above, addToArr obeys our first rule and second rule, our result is now predictable. At line 1 we make a copy of arr by spreading arr elements which gave us the capability to not mutate the original arr. it's also important to note that spread operator does shallow copying of values.

3) Pure functions depends only on the arguments passed to them. What this actually means is a pure function is self-contained, it does not depend on values outside its scope to determine its final value. let's illustrate this:

const b = 6
const sum1 = (a) => (a + b) //  line 1 
const sum2 =  (a, b = 1) => (a + b) line // 2

sum1 is considered an impure function because it takes value outside its scope to determine the final result which could be changed. The value of b in sum1 could easily be changed by external code which makes the function to unpredictable. sum2 corrects the defect in sum1.

Hence for a function to consider a pure function, the three rules above must all be satisfied, violation of any automatically makes the function impure. Finally, pure functions make our code more predictable and testable.