TransWikia.com

Running a value through an array of functions

Stack Overflow Asked by Lars Holdaas on February 14, 2021

So I have a form handling system set up where I can pass value formatting options that will change the input to fit a certain formatting (for instance stripping non-number values, enforcing max-length, adding hyphens at every X interval etc) and I want to create a function that creates a combined formatter of an arbitrary number of more minute formatters, and runs the value through these in order.

For instance a formatter could be, in the case of numbers only:

const numberFormatter = value => value.replace(.replace(/[^d]/g, '');

But I also have createFormatter functions, like for max length:

export const createMaxLengthFormatter = (maxLength) => (value) => value
  .slice(0, maxLength);

The way I use them is usually like this:

const someNumberInput = createFormField({
   ...otherParams,
  valueFormatter: createMaxLengthFormatter(8),
})

However I want to be able to do something akin to this:

const someFourDigitNumberInput = createFormField({
  ...otherParams,
  valueFormatter: combineFormatters(numberFormatter, createMaxLengthFormatter(4)),
});

Any suggestions how to implement combineFormatters in an elegant ESNEXT way?

2 Answers

So thanks to @andy-ray pointing me in the right direction I ended up with one solution that seems to be working fine:

export const combineFormatters = (...formatters) => (value) => formatters
  .reduce((currentValue, formatter) => formatter(currentValue), value);

Leaving it up as a solution for now, but not marking it as the correct one in case somebody comes up with a more elegant/correct solution for this problem. Though it does indeed seem to be doing the job as intended.

Correct answer by Lars Holdaas on February 14, 2021

This is a typical case of function composition. The compose high order function would goes like:

// compose from right to left
const compose = (...fns) => fns.reduce((f, g) => x => f(g(x)))

// compose from left to right
const compose = (...fns) => fns.reduce((f, g) => x => g(f(x)))

I would say this implementation is elegant in the sense that it looks so close to the mathematical expression. Pleasing to the eye!

However it will produce a deep calling stack, because of the function-inside-function form. Your implementation would be more memory friendly, and is equivalent in effect.

Answered by hackape on February 14, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP