1. What is Compose
In algebra, function composition allows you to apply one function to the output of another function. It looks like this;
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!