Functional programing
Functional programming
from this Medium article
Instead of for loops
const list1to100 = () => {
return new Array(100).fill(null).map((x, i) => i + 1)
}
// or in short...
Array(10)
.fill(null)
.map((x, i) => console.log(i))
Basic compose function
const compose =
(...fns) =>
(x) =>
fns.reduceRight((res, fn) => fn(res), x)
// Usage
const centsToDollars = compose(
addSeparators,
addDollarSign,
roundTo2dp,
divideBy100
)
Basic Pipe function in typescript
const pipe =
<T>(...fns: Array<(arg: T) => T>) =>
(value: T) =>
fns.reduce((acc, fn) => fn(acc), value)
Use tap and Trace for debugging inside compose
const tap = (f) => (x) => {
f(x)
return x
}
const trace = (label) => tap(console.log.bind(console, label + ':'))
// Debugging implemented to use case.
const centsToDollars = compose(
trace('addSeparators'),
addSeparators,
trace('addDollarSign'),
addDollarSign,
trace('roundTo2dp'),
roundTo2dp,
trace('divideBy100'),
divideBy100,
trace('argument')
)
/* Output
argument: 100000000
divideBy100: 1000000
roundTo2dp: 1000000.00
addDollarSign: $1000000.00
addSeparators: $1,000,000.00
*/
Container
Use a container to encapsulate “side-effecty” operations.
class Container {
constructor(fn) {
this.value = fn
if (!isFunction(this.value) && !isAsync(this.value)) {
throw new TypeError(
`Container expects a function, not a ${typeof this.value}.`
)
}
}
run() {
return this.value()
}
map(fn) {
if (!isFunction(fn) && !isAsync(fn)) {
throw new TypeError(
`The map method expects a function, not a ${typeof fn}.`
)
}
return new Container(() =>
isPromise(this.value()) ? this.value().then(fn) : fn(this.value())
)
}
}
// Usage
const sayHello = () => 'Hello'
const addName = (name, str) => str + ' ' + name
const container = new Container(sayHello)
const greet = container
.map(addName.bind(this, 'Joe Bloggs'))
.map(tap(console.log))