Функциональное программирование

Подход, при котором программа строится из функций без побочных эффектов, а данные не меняются, а преобразуются в новые.

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

Основные идеи

  • Чистые функции. Результат зависит только от аргументов, а побочных эффектов нет. Такую функцию можно вызвать сколько угодно раз — ответ будет тем же.
  • Неизменяемость. Данные не правят на месте: чтобы изменить список, создают новый.
  • Функции как значения. Функцию можно передать в другую функцию или вернуть из нее. Функции, принимающие функции, называют функциями высшего порядка.
  • Композиция. Сложная обработка собирается из цепочки простых шагов.
  • Рекурсия вместо циклов с изменяемым счетчиком.

Пример

Посчитать сумму оплаченных заказов на JavaScript в функциональном стиле:

// JavaScript
const paidTotal = orders
  .filter(order => order.status === "paid")
  .map(order => order.amount)
  .reduce((sum, amount) => sum + amount, 0);

Три шага — отобрать, взять сумму, сложить — записаны как цепочка, а исходный список orders не меняется. Тот же прием есть в Java (Stream API), C# (LINQ), Kotlin и Python.

Зачем это нужно

  • Предсказуемость и тесты. Чистую функцию проверяют одним вызовом: подали данные — сравнили ответ. Не нужно готовить состояние системы.
  • Безопасный параллелизм. Если данные не меняются, потоки не мешают друг другу — нет гонок за общие переменные. Подробнее — в термине «Параллелизм».
  • Понятная обработка данных. Конвейеры преобразований хорошо подходят для отчетов, выгрузок и потоковой обработки событий.

Языки и применение

Полностью функциональные языки — Haskell, Clojure, Erlang и Elixir, F#; Scala сочетает ФП с объектным подходом. Но чаще идеи ФП используют в обычных языках: JavaScript, TypeScript, Kotlin, Java. Библиотека React описывает интерфейс как функцию от данных, а неизменяемость состояния — одно из ее основных правил.

Ограничения

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