Введение

Функциональное программирование — это парадигма программирования, которая делает упор на написание кода с использованием функций в качестве основных строительных блоков. В функциональном программировании функции рассматриваются как объекты первого класса, что означает, что они могут быть переданы в качестве аргументов другим функциям, возвращены из функций и сохранены в переменных.

В JavaScript функции высшего порядка — это функции, которые могут принимать другие функции в качестве аргументов или возвращать функции в качестве результата. Две популярные функции высшего порядка, используемые в функциональном программировании, — это функции pipe и compose.

Функция трубы

Функция канала — это функция более высокого порядка, которая принимает две или более функций в качестве аргументов и возвращает новую функцию. Возвращаемая функция принимает ввод, применяет к нему каждую из предоставленных функций по порядку, передавая вывод каждой функции в качестве ввода следующей функции. Окончательный вывод является результатом последней функции в конвейере.

Вот пример использования функции канала:

const pipe = (...fns) => (x) => fns.reduce((acc, f) => f(acc), x);

const addFive = (x) => x + 5;
const square = (x) => x * x;
const double = (x) => x * 2;

const result = pipe(addFive, square, double)(2); // Returns 98

console.log(result);

В этом примере мы определяем три функции: addFive, square и double. Затем мы используем функцию pipe для создания новой функции, которая применяет каждую из этих функций по порядку к аргументам (2). Результатом является значение 98.

Написать функцию

Функция compose похожа на функцию pipe, но применяет функции в обратном порядке. Функция compose принимает две или более функций в качестве аргументов и возвращает новую функцию, которая применяет каждую функцию в обратном порядке.

Вот пример использования функции compose:

const compose = (...fns) => (x) => fns.reduceRight((acc, f) => f(acc), x);

const addFive = (x) => x+ 5;
const square = (x) => x * x;
const double = (x) => x * 2;

const result = compose(double, square, addFive)(2); // Returns 98

console.log(result);

В этом примере мы определяем три функции: addFive, square и double. Затем мы используем функцию compose для создания новой функции, которая применяет каждую из этих функций в обратном порядке к аргументам (2). Результатом является значение 98.

Дополнительные примеры

Есть много способов использовать функции конвейера и компоновки в JavaScript. Вот некоторые примеры:

Пример 1: Преобразование данных

Предположим, у нас есть массив пользовательских объектов, и мы хотим отсортировать массив по возрасту, отфильтровать его, чтобы включить только пользователей в возрасте 25 лет, а затем сопоставить оставшихся пользователей с их именами. Для этого мы можем использовать функции sort, filter и map, но это может быть сложно прочитать и понять код. Вместо этого мы можем использовать функцию pipe, чтобы связать эти функции вместе:

const users = [
  { name: 'Sumit', age: 38 },
  { name: 'Jasim', age: 30 },
  { name: 'Rahim', age: 20 },
];

const sortByAge = (a, b) => a.age - b.age;
const filterByAge = (age) => (user) => user.age === age;
const mapByName = (user) => user.name;

const result = pipe(
  (users) => users.sort(sortByAge),
  (users) => users.filter(filterByAge(38)),
  (users) => users.map(mapByName)
)(users);

console.log(result); // Returns ['Sumit']

В этом примере мы определяем три функции: sortByAge, filterByAge и mapByName. Затем мы используем функцию pipe, чтобы связать эти функции вместе, чтобы отсортировать, отфильтровать и отобразить массив users. Конечным результатом является массив, содержащий имена пользователей, которым исполнилось 38 лет.

Пример 2: Функциональная композиция

Предположим, у нас есть две функции, g и f, и мы хотим создать новую функцию, которая применяет g к результату f. Мы можем использовать функцию compose для создания этой новой функции:

const g = (x) => x + 1;
const f = (x) => x * 2;

const h = compose(g, f);

console.log(h(3)); // Returns 7

В этом примере мы определяем две функции, g и f. Затем мы используем функцию compose для создания новой функции h, которая применяет g к результату f. Затем мы можем вызвать h с аргументом 3, который возвращает значение 7.

Пример 3: ПО промежуточного слоя Redux

В библиотеке управления состоянием Redux промежуточное ПО — это функция, которая перехватывает действия, отправляемые в хранилище, и может изменять их, отправлять дополнительные действия или выполнять другие побочные эффекты. Функции промежуточного программного обеспечения обычно составляются вместе с использованием функции compose.

Вот пример использования функции compose для создания промежуточного ПО Redux:

const loggerMiddleware = (store) => (next) => (action) => {
  console.log(`Action: ${action.type}, State: ${JSON.stringify(store.getState())}`);
  return next(action);
};

const errorMiddleware = (store) => (next) => (action) => {
  try {
    return next(action);
  } catch (error) {
    console.error(`Error: ${error}`);
    throw error;
  }
};

const middleware = compose(loggerMiddleware, errorMiddleware);

// Usage in Redux store
const store = createStore(reducer, initialState, middleware);

В этом примере мы определяем две функции промежуточного программного обеспечения, loggerMiddleware и errorMiddleware. Затем мы используем функцию compose для создания новой функции промежуточного программного обеспечения middleware, которая объединяет эти две функции промежуточного программного обеспечения. Затем мы можем передать middleware функции createStore при создании хранилища Redux, чтобы применить обе промежуточные функции к действиям, отправляемым в хранилище.

Заключение

В заключение отметим, что функции pipe и compose являются полезными функциями высшего порядка для функционального программирования в JavaScript. Они позволяют объединить несколько функций в цепочку для создания новой функции, которая применяет все функции за одну операцию. Это может сделать ваш код более читабельным, кратким и компонуемым.