Javascript – Using compose with reduce

Tags: ,



I am learning functional programming with javascript. I have learned that 2 parameters are needed for reduce. Accumalator and the actual value and if we don’t supply the initial value, the first argument is used. but I can’t understand how the purchaseItem functions is working in the code below. can anyone please explain.

const user = {
    name: 'Lachi',
    active: true,
    cart: [],
    purchases: []
}
let history = []
const compose = (f, g) => (...args) => f(g(...args))

console.log(purchaseItem(
    emptyCart, 
    buyItem, 
    applyTaxToItems, 
    addItemToCart
)(user, {name: 'laptop', price: 200}))

function purchaseItem(...fns) {
    console.log(fns)
    return fns.reduce(compose)
}

function addItemToCart (user, item) {
    history.push(user)
    const updatedCart = user.cart.concat(item)
    return Object.assign({}, user, { cart: updatedCart })
}

function applyTaxToItems(user) {
    history.push(user)
    const {cart} = user
    const taxRate = 1.3
    const updatedCart = cart.map(item => {
        return {
            name: item.name,
            price: item.price * taxRate
        }
    })
    return Object.assign({}, user, { cart: updatedCart })
}

function buyItem(user) {
    history.push(user)
    return Object.assign({}, user, { purchases: user.cart })
}

function emptyCart(user) {
    history.push(user)
    return Object.assign({}, user, {cart: []})
}

Answer

It’s a way of creating a pipeline of functions whereby the output from one function is used as the parameter of the next, so we end up with a composed function that is effectively

(...args) => 
    emptyCart( 
        buyItem( 
            applyTaxToItems( 
                addItemToCart(...args) 
            ) 
        ) 
    )

Writing the reduce out in longhand might help in understanding:

fns.reduce((acc, currentFn) => compose(acc, currentFn))


Source: stackoverflow