Concepts in functional programming

 

Pure functions

 

Most important concept in functional programming is the concept of pure functions. This means that the output of a function should only depend on its inputs.

Example:

function toMyString(val) {
  return val.toString();
}

Function toMyString takes argument val and returns value formatted as a string.
If you want to make this impure function, you can mutate number variable directly like this:

let num = 123;

function toMyString(val) {
  num = val;
  return val.toString();
}

This would be considered as a side-effect and functional code should not have side-effects. It should not rely on any outside value to produce a return value.

Pure functions are easier to test because you don’t have to think about anything happening outside of the function.

 

Immutable data

 

Another principle of functional programming is immutable data. Immutable data is data that can not be or should not be modified or deleted. Functional code is stateless meaning that when data is created, it is never mutated.

 

Example:

const data = Object.freeze([1,2,3,4,5,6]);

Object.freeze prevents us from doing things like Array.push, which you wouldn’t do in functional programming.

Functions as Arguments

 

When data has to change, you’ll often pass functions as arguments to other functions.

 

Example:

const addHashtag = (val) => toString(val) + ' #';

Here we have a typical first order function, which takes a value and appends a hashtag to a string.

A higher order function is one that either takes a function as argument or returns a function itself. Javascript has built-in higher order functions for arrays such as map, so instead of using a for loop, we can just pass our function addHashtag to map, which will run our addHashtag function on every element of the array and transform the values.

const data = Object.freeze([1,2,3,4,5,6]);

const addHashtag = (val) => toString(val) + '#';

const hashtagData = data.map(addHashtag)
console.log(emojiData); // ['1 #', '2 #', '3 #', '4 #', '5 #', '6 #']

Another thing we can do is to create functions that return functions. This is very useful when you want to start with some basic functionality and extend it with some dynamic data. 

 

Example:

In code above, we have a base function called appendEmoji and we use it to compose more complex functions. Inner function takes both of the arguments and adds them together.

We can use this to make specialized functions that point to a specific emoji. Rain and sun functions point to rain emoji and sun emoji, respectively. 

The end result is concise and readable code that doesn’t rely on any shared state that will make it difficult to test.