# 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](https://cdn.hashnode.com/res/hashnode/image/upload/v1631182280110/3gKVaNA5X.png)

We can also apply same thing with javascript.

```jsx
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;

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

And then a function that uppercases strings:

```jsx
// 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`


```jsx
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;

```jsx
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**.

```jsx
// 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
```jsx
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!


## Links
- 🔗 [Function Composition in JavaScript](https://www.freecodecamp.org/news/function-composition-in-javascript/)

- 🔗 [Compose and Pipe in JavaScript](https://betterprogramming.pub/compose-and-pipe-in-javascript-medium-d1e1b2b21f83)
- 🔗 [Array.prototype.reduceRight() - JavaScript | MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/ReduceRight)

