What is Function Composition

What is Function Composition

1. What is Compose

In algebra, function composition allows you to apply one function to the output of another function. It looks like this;

Compose Example

We can also apply same thing with javascript.

const compose = (g, f) => x => g(f(x));

2. Example

I can tell, you are a little bit confused. Let me break it down for you;

Let’s say we want to get the name of a user and uppercase it. First of all, we have to write a function that extracts the name of the user;

const user = {name: 'Furkan', lastName: "Cool"}
// Returns -> String
const getUserName = (user) => user.name
getUserName(user)
// 'Furkan'

And then a function that uppercases strings:

// Accepts -> String
// Returns -> String
const upperCase = (string) => string.toUpperCase()
upperCase('Furkan')
// 'FURKAN'

Notice that one function's return value is other function's parameter type.


Compose function will return a function that will executes these two functions.

In our example they are: getUsername & upperCase

const compose = (G, F) => X => G(F(X));

// 'X' in compose
const user = {name: 'Furkan', lastName: "Cool"}

// 'F' in compose
const getUserName = (user) => user.name

// 'G' in compose
const upperCase = (string) => string.toUpperCase()

// Returned function in compose
const getUserNameAndUpperCase = compose(upperCase, getUserName)

// user -> 'X' in compose function
getUserNameAndUpperCase(user); 
//'FURKAN'

3. Scale Problem

The problem with this implementation of compose() is that it takes as parameters just N functions (upperCase & getUserName).

Let’s suppose we want to add another function that returns the full name of the user;

const getUserFullName = (name) => name + " " + user.lastName;
getUserFullName(‘FURKAN’);
// 'FURKAN Cool'

Did you see the problem here?

4. Using compose with reduceRight function

For this case instead of giving N functions and manually changing them, we can use the spread syntax (...) and give an array of functions as an argument to compose function.

// reduceRight calls from right to left instead of left to right
const compose = (...fns) => (initialVal) => fns.reduceRight((val, fn) => fn(val), initialVal);

The reduceRight() method applies a function against an accumulator and each value of the array (from right-to-left) to reduce it to a single value.

5. Full Example

const compose = (...fns) => (initialVal) => {
  return fns.reduceRight((val, fn) => fn(val), initialVal)
};
const user = { name: 'Furkan', lastName: "Cool" }
const getUserName = (user) => user.name
const upperCase = (string) => string.toUpperCase()
const getUserFullName= (name) => name + " " + user.lastName
compose(firstFour, upperCase, getUserFullName)(user);
// 'FURKAN Cool'

Conclusion

Composition is really insteresting subject. Instead of unreadable nested functions, you can organize and chain your functions with each other. And it is super cool!