Functional (Programming) mindset


Open Source Your Knowledge, Become a Contributor

Technology knowledge has to be shared and made accessible for free. Join the movement.

Create Content

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 **

Impure? NO thanks!


but why?


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  

but why?


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

We can also makes the minimum immutable:

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

but why?

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

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


but why?


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

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

Further information: Object.freeze()

but why?


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

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]

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*

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


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'};
const fourWheelCar = addWheels(noWheelCar, 4);

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 }


but why?


"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.

Open Source Your Knowledge: become a Contributor and help others learn. Create New Content