# 🪴\zansh.in\js

## # reducers / transducers / compose

Build a map and filter transducer little by little, compose them, and avoid talking about math.

### # reduce()

``````const startWith = []

const oneItem = () => 
.reduce(doubleAndAppend, startWith)

const twoItems = () => [1, 2]
.reduce(doubleAndAppend, startWith)

const threeItems = () => [1, 2, 3]
.reduce(doubleAndAppend, startWith)
``````

### # doubleAndAppend()

``````const one = () =>
doubleAndAppend([], 1)

const two = () =>
doubleAndAppend(, 2)

const three = () =>
doubleAndAppend([2, 4], 3)

function doubleAndAppend(accumulator, x) {
return [...accumulator, x * 2]
}
``````

### # double() + append()

``````const map = () =>
[1, 2, 3].reduce(doubleAndAppend, [])

function doubleAndAppend(accumulator, x) {
return append(accumulator, double(x))
}

function double(x) {
return x * 2
}

function append(accumulator, x) {
return [...accumulator, x]
}
``````

### # TransformAndAppend()

``````const doubleAndAppend = () =>
[1, 2, 3].reduce(
TransformAndAppend(double),
[]
)

function TransformAndAppend(transform) {
return (accumulator, x) =>
append(accumulator, transform(x))
}
``````

### # TransformAndBuild() / mapping transducer

``````const doubleAndAppend = () =>
[1, 2, 3].reduce(
TransformAndBuild(double)(append),
[]
)

function TransformAndBuild(transform) {
return build => {
return (accumulator, x) =>
build(accumulator, transform(x))
}
}
``````

### # appendIfDefined()

``````const excludeUndefined = () =>
[1, 2, undefined, 3].reduce(
TransformAndBuild(x => x)(
appendIfDefined
),
[]
)

function appendIfDefined(accumulator, x) {
return defined(x)
? [...accumulator, x]
: accumulator
}

function defined(x) {
return x !== undefined
}
``````

### # map() + filter() transducers

``````const doubleAndAppend =
map(double)(append)

const appendIfDefined =
filter(defined)(append)

const runMap = () =>
[1, 2, 3]
.reduce(doubleAndAppend, [])

const runFilter = () =>
[1, 2, undefined, 3]
.reduce(appendIfDefined, [])

function map(transform) {
return build => (acc, x) =>
build(acc, transform(x))
}

function filter(predicate) {
return build => (acc, x) =>
predicate(x) ? build(acc, x) : acc
}
``````

### # compose()

``````const doubleNumbers = map(double)
const onlyDefined = filter(defined)

const manually = () =>
[1, 2, undefined, 3].reduce(
onlyDefined(doubleNumbers(append)),
[]
)

const functionally = () =>
[1, 2, undefined, 3].reduce(
compose(
onlyDefined,
doubleNumbers
)(append),
[]
)

function compose(...fns) {
return x =>
fns.reduceRight((y, f) => {
const acc = f(y)
return acc
}, x)
}
``````