Создание pipe и compose
Реализуйте композицию слева направо и справа налево.
«Создание pipe и compose» — бесплатный урок JavaScript Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения JavaScript Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс JavaScript Academy содержит 4 уроков всего.
От двух функций к множеству
compose с двумя аргументами ограничивает возможности. Настоящие конвейеры объединяют множество шагов. На этом уроке вы создадите универсальные compose и pipe с помощью reduce и reduceRight.
pipe: слева направо
pipe читает шаги в порядке выполнения: первая функция выполняется первой. pipe(a, b, c)(x) равно c(b(a(x))). Большинству такой порядок кажется естественнее, чем порядок в compose.
const pipe = (...fns) => x => fns.reduce((acc, fn) => fn(acc), x);
const inc = n => n + 1;
const double = n => n * 2;
console.log(pipe(inc, double)(5));Как reduce управляет pipe
reduce начинает со входного значения в качестве аккумулятора и по очереди применяет каждую функцию, передавая её результат следующей. Начальное значение x запускает цепочку.
const pipe = (...fns) => x => fns.reduce((acc, fn) => fn(acc), x);
const steps = pipe(
n => n + 1,
n => n * 3,
n => n - 2
);
console.log(steps(4));compose с reduceRight
compose — это pipe в обратном направлении. Использование reduceRight обходит список функций с конца, поэтому самая правая функция выполняется первой, как в f(g(x)).
const compose = (...fns) => x => fns.reduceRight((acc, fn) => fn(acc), x);
const inc = n => n + 1;
const double = n => n * 2;
console.log(compose(inc, double)(5));pipe и compose — зеркальные варианты
Один и тот же список функций даёт разные результаты в pipe и compose, потому что направление меняется на противоположное. Выбирайте вариант в зависимости от того, как вы хотите читать шаги.
const pipe = (...fns) => x => fns.reduce((acc, fn) => fn(acc), x);
const compose = (...fns) => x => fns.reduceRight((acc, fn) => fn(acc), x);
const inc = n => n + 1;
const square = n => n * n;
console.log(pipe(inc, square)(3));
console.log(compose(inc, square)(3));compose как обращённый pipe
Можно определить compose через pipe, развернув список функций. Это показывает, насколько тесно они связаны.
const pipe = (...fns) => x => fns.reduce((acc, fn) => fn(acc), x);
const compose = (...fns) => pipe(...fns.reverse());
const inc = n => n + 1;
const double = n => n * 2;
console.log(compose(inc, double)(5));Настоящий текстовый конвейер
Создайте генератор читаемых идентификаторов из небольших строковых функций с помощью pipe. Каждый шаг выполняет одну задачу и его легко протестировать отдельно.
const pipe = (...fns) => x => fns.reduce((acc, fn) => fn(acc), x);
const slugify = pipe(
s => s.trim(),
s => s.toLowerCase(),
s => s.replace(/\s+/g, '-')
);
console.log(slugify(' Hello World Example '));Композиция операций над массивами
Конвейеры работают с любыми типами данных, включая массивы. Объедините фильтрацию и преобразование элементов в одно именованное преобразование.
const pipe = (...fns) => x => fns.reduce((acc, fn) => fn(acc), x);
const process = pipe(
arr => arr.filter(n => n % 2 === 0),
arr => arr.map(n => n * 10)
);
console.log(process([1, 2, 3, 4, 5, 6]));Граничный случай тождественного преобразования
Вызов pipe() без функций возвращает входное значение без изменений, потому что reduce просто возвращает начальное значение. Такое тождественное поведение позволяет безопасно вызывать вспомогательные инструменты без шагов.
const pipe = (...fns) => x => fns.reduce((acc, fn) => fn(acc), x);
const identity = pipe();
console.log(identity(42));
console.log(identity('unchanged'));Объединение с каррированием
Curried-функции с частично применёнными аргументами напрямую подключаются к конвейерам. Каждая становится аккуратным шагом с одним аргументом.
const pipe = (...fns) => x => fns.reduce((acc, fn) => fn(acc), x);
const add = a => b => a + b;
const times = a => b => a * b;
const calc = pipe(add(3), times(2), add(-1));
console.log(calc(5));Выбор между pipe и compose
Используйте pipe, если хотите читать шаги сверху вниз в порядке выполнения. Используйте compose, если нужно соответствовать математической записи f(g(x)). Оба варианта являются однострочными оболочками над reduce и широко используются в библиотеках функционального программирования.
const pipe = (...fns) => x => fns.reduce((acc, fn) => fn(acc), x);
const normalize = pipe(
s => s.trim(),
s => s.replace(/[^a-z0-9]+/gi, ' '),
s => s.toUpperCase()
);
console.log(normalize(' a-b_c!d '));Быстрая проверка
Какой метод массива заставляет compose выполнять функции справа налево?
Повторение: pipe и compose
Вы создали универсальные вспомогательные инструменты для композиции:
- pipe использует
reduceдля выполнения слева направо. - compose использует
reduceRightдля выполнения справа налево. composeможно определить какpipeс развёрнутым списком.- Пустые конвейеры действуют как тождественное преобразование, а curried-шаги легко встраиваются.
Часто задаваемые вопросы
Урок «Создание pipe и compose» бесплатный?
Да — полный текст урока «Создание pipe и compose» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс JavaScript Academy, подпишись на CoddyKit PRO. Курс JavaScript Academy содержит 4 уроков всего.
Чему я научусь в уроке «Создание pipe и compose»?
Реализуйте композицию слева направо и справа налево. Ты практикуешь JavaScript Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать JavaScript Academy?
Предыдущий опыт не требуется. JavaScript Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.
Сколько времени занимает урок «Создание pipe и compose»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке JavaScript Academy?
Да. Каждый урок JavaScript Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Частичное применение
- Каррирование функций
- Композиция функций
- Создание pipe и compose