Введение
Функциональное программирование — это парадигма программирования, которая делает упор на написание кода с использованием функций в качестве основных строительных блоков. В функциональном программировании функции рассматриваются как объекты первого класса, что означает, что они могут быть переданы в качестве аргументов другим функциям, возвращены из функций и сохранены в переменных.
В 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. Они позволяют объединить несколько функций в цепочку для создания новой функции, которая применяет все функции за одну операцию. Это может сделать ваш код более читабельным, кратким и компонуемым.