ФП: функции высшего порядка, compose и pipe
↑ 8.1 Парадигмы: ООП, ФП, SOLID · ← Предыдущая · → Следующая
Зачем это на собесе
ФП-подход лежит в основе Vue composition API, Redux, RxJS; просят реализовать compose/pipe/curry.
Ключевые идеи
- чистые функции: результат зависит только от аргументов, без побочных эффектов;
- иммутабельность: новое значение вместо изменения старого;
- функции — значения: передаём, возвращаем, композируем;
- функции высшего порядка (HOF): принимают или возвращают функции.
HOF
const withLogging = <A extends unknown[], R>(fn: (...a: A) => R) =>
(...args: A): R => { console.log('call', fn.name, args); return fn(...args) }
const debounce = <A extends unknown[]>(fn: (...a: A) => void, ms: number) => {
let t: ReturnType<typeof setTimeout>
return (...args: A) => { clearTimeout(t); t = setTimeout(() => fn(...args), ms) }
}map, filter, reduce, sort, Array.from — тоже HOF.
pipe и compose
const pipe = <T>(...fns: Array<(x: T) => T>) => (x: T) => fns.reduce((acc, fn) => fn(acc), x)
const compose = <T>(...fns: Array<(x: T) => T>) => (x: T) => fns.reduceRight((acc, fn) => fn(acc), x)
const slugify = pipe<string>(
s => s.trim(),
s => s.toLowerCase(),
s => s.replace(/\s+/g, '-'),
)
slugify(' Hello World ') // 'hello-world'pipe читается слева направо, compose — справа налево.
Каррирование и частичное применение
const curry = (fn: Function) => function c(...a: any[]): any {
return a.length >= fn.length ? fn(...a) : (...b: any[]) => c(...a, ...b)
}
const add = curry((a: number, b: number, c: number) => a + b + c)
add(1)(2)(3); add(1, 2)(3)Иммутабельность
const next = { ...state, user: { ...state.user, name: 'Аня' } }
const list2 = [...list, item]
const list3 = list.filter(x => x.id !== id)
structuredClone(obj) // глубокая копияБиблиотеки: Immer (мутирующий синтаксис поверх неизменяемости).
Во фронтенде
Редьюсеры, селекторы, computed, чистые преобразования данных, RxJS-операторы, мемоизация.
Вопросы с ответами
Что такое чистая функция и зачем она?
Функция без побочных эффектов, результат зависит только от аргументов. Проще тестировать, кэшировать, распараллеливать и рассуждать о ней.
Разница между pipe и compose?
Порядок применения: pipe — слева направо, compose — справа налево.