Композиция функций в программировании
Композиция функций — это преобразование последовательности функций (значений функционального типа: функций, анонимных функций, лямбда-выражений, методов) в одну функцию (значение функционального типа). При композиции результат предыдущей функции становится аргументом следующей, которая, в свою очередь, возвращает результат, который передается в качестве а аргумента третьей и так далее. Пример на двух функциях:<syntaxhighlight lang="javascript"> // композиция двух функций
const compose = (f1, f2) => x => f2(f1(x));
// пример использования
const upperCapital = s => s.replace(
/\w+/g, word => word.charAt(0).toUpperCase() + word.substr(1)
);
const lower = s => typeof(s) === 'string' ? s.toLowerCase() : ;
const capitalize = compose(lower, upperCapital);
// Сравниваем суперпозицию и композицию функций
console.log(upperCapital(lower('MARCUS AURELIUS'))); console.log(capitalize('MARCUS AURELIUS')); </syntaxhighlight>Композиция произвольного кол-ва функций:<syntaxhighlight lang="javascript"> const compose = (...funcs) => (...args) => (
funcs.reduce((args, fn) => [fn(...args)], args)
); </syntaxhighlight>
Асинхронная композиция[править]
В асинхронном программировании функции возвращают значения в колбеки, и композиция может быть осуществлена связыванием последоваельности асинхронных функций в цепочку колбеков, когда следующая функция становится колбеком для предыдущей (это последовательная композиция) или параллельная композиция, которая порождает функцию, завершающуюся при завершении всех колбеков из последовательности функций. <syntaxhighlight lang="javascript"> // вспомогательная функция асинхронный reduce const reduceAsync = (items, performer, done, initialValue) => {
const nseted = initialValue === undefined; let counter = nseted ? 1 : 0; let previous = nseted ? items[0] : initialValue; let current = nseted ? items[1] : items[0];
function response(err, data) { if (!err && counter !== items.length - 1) { ++counter; previous = data; current = items[counter]; performer(previous, current, response, counter, items); } else if (done) { done(err, data); } }
performer(previous, current, response, counter, items);
};
// асинхронная композиция // funcs - array of parametrs for functions // args - array of functions // args[i] - function // args[-1] - done(err, data) // const composeAsync = (funcs, ...args) => (
() => reduceAsync( args.slice(0, -1), (params, fn, done) => fn(...[].concat(params).concat(done)), args[args.length - 1], funcs )
); </syntaxhighlight>