Композиция функций — это мощный инструмент для работы, например:
const add = (x, y) => x + y;
const double = (x) => add(x, x);
double(add(2, 3)); // 10
Но в сложных выражениях композитные функции могут быть сложны для понимания, например: double(double(add(7, add(add(5, add(4, 5)), 4))))); // 100
Куда удобнее было бы применять эти операции последовательно, слева направо, например:
s.add(4,5).add(5).add(4).add(7).double().double().calculate(); // 100
Ваша задача реализовать ‘sequence’ функцию:
let s = sequence({ add, double });
Как вы можете видеть, эта функция принимает объект с методами add и double и возвращает объект, который позволяет вам вызывать ваши методы цепочкой. Результат можно получить, вызвав метод ‘calculate()’.
Методы в цепочке принимают определенное количество аргументов. Первая функция в этой цепочке получает все аргументы. В последующих функциях первый аргумент — результат выполнения предыдущей функции, а остальные передаются вручную.
Стоит учесть, что цепочки могут быть переиспользованы:
s.add(3, 4).calculate(); // 7
s.add(1, 2).calculate(); // 3
Ещё примеры:
let s1 = s.add(1, 2); s1.calculate(); // == add(1, 2) == 3
s1.double().calculate(); // == double(add(1, 2)) == 6
s1.add(1).calculate(); // == add(add(1, 2), 1) == 4
s1.calculate(); // == add(1, 2) == 3
let s2 = s1.add(5); s2.double().calculate(); // == double(add(add(1, 2), 5)) == 16
s2.add(3).calculate(); // == add(s1.add(add(1, 2), 5), 3) == 11
s2.calculate(); // == add(add(1, 2), 5) == 8
s1.calculate(); // == add(1, 2) == 3
Все приведенные примеры основаны на реализации add и double как функций сложения и удвоения численных аргументов для удобства отладки. Однако передача функций add и double параметрами в sequence позволяет абстрагироваться от их реализации. В sequence могут быть переданы функции add и double оперирующие строками или более сложными объектами.
Функция sequence должна успешно проходить все указанные тест-кейсы.
Пример реализации Sequencing Functions
function sequence(funcObj) { let funcArray = []; function wrapper(...args) { for (let i = 0; i < funcArray.length; i++) { args = [funcArray[i](...args)]; } return args[0]; } Object.keys(funcObj).forEach(key => { wrapper[key] = (...args) => { funcArray.push(funcObj[key].bind(null, ...args)); return wrapper; }; }); wrapper.calculate = () => { return wrapper(); }; return wrapper; } const add = (x, y) => x + y; const double = (x) => add(x, x); let s = sequence({ add, double }); console.log(s.add(4,5).add(5).add(4).add(7).double().double().calculate()); // 100