# Function composition

## c (x) = g ( f ( x ) )

Monad - design pattern to deal with side effects keeping your functions pure.

Design pattern that allows you to write programs in a more abstract way by taking away some boilerplate code that's needed by the program logic.

The idea is that gluing (side effects, io) is made outside of the main functions (which can stay pure), but inside the compose helper.

# Coding exercise:

## built with function composition

```const add5 = x => x + 5
const double = x => x * 2
const deduct3 = x => x - 3```

Ex. 1: Build application as a composition of "base" functions

```const add5 = x => x + 5
const double = x => x * 2```
```const compose = (f, g) => x => g(f(x)))
```
`const app = compose(add5, double)`
```app(3)

// >>> (3 + 5) * 2 = 16```
```const compose = fns => (x => {
return fns.reduce((acc, fn) => {
return fn(acc)
}, x)
})
```
```const app = compose([
double,
deduct3
])
```
```app(5)
// >>> 17```
```const app2 = compose([
app,
double
])

app2(5)
// >>> 34```
```const add5 = x =>  x + 5
const double = x =>  x * 2
const deduct3 = x =>  x - 3
```

Ex. 2. New requirement: explain how the result was calculated:                10 + 5 - 3 * 2 = 24

```const compose = fns => x => {
return fns.reduce((acc, fn) => {
return fn(acc)
}, x)
}
```
```const app = compose([
deduct3,
double,
])
```
```const compose = fns => x => {
return fns.reduce(([x, desc], fn) => {
const [x2, desc2] = fn(x)
return [x2, desc + ' ' + desc2]
}, [x, ''])
}
```
```function run(x) {
const [y, desc] = app(x)
console.log(x + desc + ' = ' + y)
}
run(10)
// >>> 10 + 5 - 3 * 2 = 24
```
```app(10)
// >>> [24, "+ 5 - 3 * 2"]
```
```[      , '+ 5']
[     , '* 2']
[     , '- 3']
```
```const add5 = x => x + 5
const double = x => x * 2
```

```const compose = fns => x => {
return fns.reduce((acc, fn) => {
return fn(acc)
}, x)
}
```
```const asyncOp = x => Promise.resolve(x + 100)
```
```// asyncOp(5).then(res => console.log(res))
```
```const app = compose([
double,
deduct3,
asyncOp
])
```
```const compose = fns => x => {
return fns.reduce((accP, fn) => {
return accP.then(acc => fn(acc))
}, Promise.resolve(x))
}
```
```function run(x) {
const resultPromise = app(x)
resultPromise.then(result => console.log(result))
}
run(5)
// >>> 117
```
```const add5 = x => [x + 5, '+ 5']
const double = x => [x * 2, '* 2']
const deduct3 = x =>
Promise.resolve([x - 3, '- 3'])

const compose = fns => x => {
return fns.reduce((acc, fn) => {
return acc.then(([x, desc]) => {
let res = fn(x)
if (!(res instanceof Promise)) {
res = Promise.resolve(res)
}
return res.then(([x2, desc2]) => {
return [x2, desc + ' ' + desc2]
})
})
}, Promise.resolve([x, '']))
}```

Ex. 4: All together

```const app = compose([
double,
deduct3
])

const app2 = compose([
app,
double
])

function run(x) {
app2(x).then(([y, desc]) => {
console.log(x + desc + '=' + y)
})
}

run(5)
// >>> 5 + 5 * 2 - 3 * 2 = 34```

- Allow construct application using composition.

```const app = compose([
double,
deduct3
])```
```const compose = fns => x => {
return fns.reduce((acc, fn) => {
return acc.then(([x, desc]) => {
let res = fn(x)
if (!(res instanceof Promise)) {
res = Promise.resolve(res)
}
return res.then(([x2, desc2]) => {
return [x2, desc + ' ' + desc2]
})
})
}, Promise.resolve([x, '']))
}```

- Hide boilerplate by making gluing inside helpers.

- Better structure code: composition VS compose helpers.

Monads - function composition on steroids