# Becoming Functional

LeoLanese
8,758 views

## The Pure (or Impure) game.

• You need to answer if the next functions are Pure Or Impure
• The question are in increasing level of difficulty.

** Level 1 **

** Level 2 **

** Level 3 **

** Level 4 **

## LEVEL 1

let minimum = 21;
const checkAge = age => age >= minimum;
checkAge(23); // true
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Pure or Impure Game?
but why?

Impure!

Impure function A side-effect here is a change of system state: it is no completely independent of outside state, due to this external call to non-constants we break the rules:

• Given the same inputs, always returns the same output
• No side-effects

FP avoids shared state, instead relying on immutable data structures and pure calculations.

const minimum = 21; // the calling to minimum makes it impure


const checkAge = (age) => {
const minimum = 21;
return age >= minimum;
};
checkAge(1); // false
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Pure or Impure Game?
but why?

Pure!

const minimum = 21; // calling minimum inside block scope make it pure

We can also makes the minimum immutable:

const immutableState = Object.freeze({ minimum: 21 });


function getDocument() {
return global.window.document;
}
getDocument()
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Pure or Impure Game?
but why?

Impure! Function depending on a value outside of its arguments.

// make it pure
function getDocument(environment) {
return environment.window.document;
}
getDocument(global);


## LEVEL 2

const minimum = Object.freeze({
usa: { old: 16 },
spain: 21,
uk: 19
})
const checkAge = age => age >= minimum.usa.old;
checkAge(23); // true
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Pure or Impure Game?
but why?

Impure!

Object.freeze() frozen objects but only superficially, do not freeze internally

// minimum object is mutable
minimum.usa.old = 60; // "{"usa":{"old":60},"spain":21,"uk":19}"

// if we want to make it freeze we need to freeze every object
Object.freeze(minimum.usa);

// then
'use strict';
minimum.usa.old = 20; // Cannot assign to read only property 'old' of object '#<Object>'


Further information: Object.freeze()

let arr = [1,2,3,4,5];
newArr = arr.map( (x) => { return x*2 });
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Pure or Impure Game?
but why?

Pure!

• .map() is a pure method which does NOT mutate data.
• There are no side effects using .map()

const arr = [1,2,3,4,5];
console.log( arr.slice(0,3) );
console.log( arr.slice(0,3) );
console.log( arr.slice(0,3) );
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Pure or Impure Game?
but why?

Pure! slice method don't mutate

console.log( arr.slice(0,3) ); // [1,2,3]
console.log( arr.slice(0,3) ); // [1,2,3]
console.log( arr.slice(0,3) ); // [1,2,3]


const arr = [1,2,3,4,5];
console.log( arr.splice(0,3) );
console.log( arr.splice(0,3) );
console.log( arr.splice(0,3) );
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Pure or Impure Game?
but why?

Impure! slice method mutate

arr.splice(0,3); // [1,2,3]
arr.splice(0,3); // [4,5]
arr.splice(0,3); // []


Tip: .splice() and .slice() They are two functions that do the exactly same thing, but mutation is where the difference is*

const arr = [1,2,3,4,5];
console.log( [...arr].reverse() );
console.log( [...arr].sort() );
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Pure or Impure Game?
but why?

const arr = [1,2,3,4,5]; arr.reverse(); // [5, 4, 3, 2, 1] reverse mutate here arr.sort(); // [1, 2, 3, 4, 5] and sort here

[...arr].reverse(); // [5, 4, 3, 2, 1] but spread operator we can avoid mutation creating a new object [...arr].sort(); // [1, 2, 3, 4, 5] but spread operator we can avoid mutation creating a new object

.reverse() and .sort() both mutate, but using the spread operator we can avoid mutation

## LEVEL 3

const addWheels = (obj, num) => Object.assign({}, obj, {wheels: num});
const noWheelTruck = {type: 'truck'};
console.log(noWheelTruck);
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Pure or Impure Game?
but why?

Origin object unchanged: {type: 'truck'}

const addWheels = (obj, num) => Object.assign({}, obj, {wheels: num}); //  pure ES5 way
const noWheelTruck = {type: 'truck'};
const fourWheelTruck = addWheels(noWheelTruck, 4); // {type: 'truck', wheels: 4}

console.log(noWheelTruck); // original object unchanged: {type: 'truck'}


const addWheels = (obj, num) => {obj['wheels'] = num};
const noWheelCar = {type: 'car'};

console.log(noWheelCar);

Pure or Impure Game?
but why?

Impure! Origin object changed: { type: 'car', wheels: 4 }

const addWheelsImpure = (obj, num) => {obj['wheels'] = num};
const noWheelCar = {type: 'car'};
const fourWheelCar = addWheels(noWheelCar, 4); // impure {type: 'car', wheels: 4}

console.log(noWheelCar) // MUTATED! origin object changed: { type: 'car', wheels: 4 }


## LEVEL 4

function returnZeroFunc() {
function fZero() {
console.log('IMPURE');
// IMPURE CODE HERE
return 0;
}
return fZero;
}
const test = returnZeroFunc();
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Pure or Impure Game?
but why?

Pure!

"A side effect isn't a side effect until it actually happens": Our returnZeroFunc() function does nothing other than return the same function, every time.

We wrapped fZero() inside another function that just returned and keep it in test:

• This function wrapping thing is a legitimate strategy.
• We can keep hiding behind functions as long as we want.
• As long as we never actually call any of these functions, they’re all theoretically pure.
• Wrapping everything in a function lets us control those effects with precision. We decide exactly when those side effects happen.