<- johnlindquist.com

Replacing Named Parameters With Function Composition

A quick little https://egghead.io lesson if you're in to that sorta thing:

Named parameters are a great feature of JavaScript, don't get me wrong, but sometimes functional composition is a more elegant solutions (I SAID SOMETIMES!).

The example I'll be refactoring looks like this:

const select = ({ to, from, array }) => array.slice(from, to)

Seems like perfectly normal code, right? Let's investigate...

What's Your Output?

Is it a String? An Array? An Object? This matters because composition requires that your output can also be the input of the next function. So you need to transform the data one step at a time. In our example that means we'll need to output an array so the next input can be an array.

For example, chopping off the end of the array:

const to = x => array => array.slice(0, x)

Then chopping off the beginning:

const from = x => array => array.slice(x)

These two functions fit together because they both have an array as input and output.

So that begs the question...

What Is Your Input?

Is your input really an object with a bunch of options?

select({ from: 3, to: 5, array: nums })

The true input there is the nums, the other options modify the nums.

array is the input. to and from modify the input.

Compare these two below:

I saw another example online using a simple formatDate function like this:

const formatDate = ({ day, month, year }) => `${month}/${day}/${year}`

The true input of that function is probably an implied empty string "". Then you can modify the string one step at a time to get the final result.

The complexity in the example below shoots through the roof compared to the snippet above, but the flexibility of "working with a string" gives you many, many more options. In fact, this is probably the beginning of an entire date formatting library.

So compare the implementations:

const formatDate = ({ day, month, year }) => `${month}/${day}/${year}`
formatDate({ day: 30, month: 6, year: 2019 })

vs. using functions:

const formatDate = compose(
day(30),
year(2019),
month(2),
)
formatDate('')

In this contrived example, notice how each named parameter is now represented by a function which modifies the input. Between the two examples, which do you think conveys the intention better? Which is more flexible for refactoring and adding features?

Ok, so that example is a little wacky, I know. Sometimes I go overboard. But hopefully I've got you thinking about what your inputs and outputs truly are and why functions are sometimes preferred over stacking on additional named parameters.