Что такое функциональное программирование?
Функциональное программирование (также его сокращенно называют ФП) – это своего рода философия создания программного обеспечения путем создания чистых функций. ФП избегает концепций разделяемых состояний и изменяемых данных, которые есть в объектно-ориентированном программировании.
Языки функционального программирования делают упор на выражениях и объявлениях, а не на выполнении операторов. Соответственно, в отличие от других процедур, которые зависят от локального и глобального состояния, значение на выходе в ФП зависит только от аргументов, которые были переданы функции.
Характеристики функционального программирования
- Функциональное программирование сосредоточено на результате, а не на процессе
- ФП делает акцент на том, что должно быть вычислено
- Данные являются неизменяемыми
- Функциональное программирование разбивает задачу на «функции»
- ФП построено на концепции математических функций, которые для вычислений используют условные выражения и рекурсию
- ФП не поддерживает итерирование, например, операторы цикла и условные операторы, такие как if-else
История функционального программирования
- Основа функционального программирования – это лямбда-исчисление. Оно было разработано в 1930-х годах для функционального применения, определения и рекурсии
- LISP – первый язык функционального программирования. Его разработал Маккарти в 1960 году
- В конце 70-х годов исследователи из Эдинбургского университета определили ML (Meta Language - метаязык).
- В начале 80-х годов язык Hope привнес алгебраические типы данных для рекурсии и эквациональных рассуждений
- В 2004 году появился новый язык функционального программирования «Scala»
Языки функционального программирования
Цель любого языка ФП – имитация математических функций. Однако базовая технология вычислений в функциональном программировании все же отличается.
Ниже приведены некоторые самые известные языки функционального программирования:
- Haskell
- SML
- Clojure
- Scala
- Erlang
- Clean
- F#
- ML/OCaml Lisp/Scheme
- XSLT
- SQL
- Mathematica
Основная терминология и базовые концепции функционального программирования
Неизменяемые данные
Неизменяемые данные подразумевают, что вам нужно просто создавать структуры данных вместо того, чтобы менять уже существующие.
Ссылочная прозрачность
Функциональные программы должны выполнять операции так, как если бы они это делали впервые. В этом случае вы будете знать, что могло или не могло произойти в процессе выполнения программы, а также ее побочные эффекты. В терминах ФП это называется ссылочной прозрачностью.
Модульный принцип организации
Модульная архитектура повышает производительность. Небольшие модули быстро пишутся, и есть большая вероятность, что они будут повторно использованы, а это, конечно, приводит к более быстрому процессу разработки программ. Помимо всего прочего, модули можно тестировать отдельно, что помогает сократить время, которое затрачивается на модульное тестирование и отладку.
Удобство сопровождения
Удобство сопровождения – это несложный термин, который означает, что ФП-программы легче поддерживать, так как вам не нужно беспокоиться о том, что за пределами функции может что-то измениться.
Полноправная функция
«Полноправная функция» - это определение, которое относится к сущностям языка программирования, которые не имеют ограничений на использование. Как следствие, полноправные функции могут появляться в программе где угодно.
Функция-замыкание
Функция-замыкание – это внутренняя функция, которая может обращаться к переменным родительской функции даже после того, как та была выполнена.
Функции высшего порядка
Функции высшего порядка могут либо принимать другие функции в качестве аргументов, либо возвращать их в качестве результата.
Функции высшего порядка допускают частичное применение или каррирование. Этот механизм подразумевает, что функция применяется к своим аргументам по очереди, поскольку каждое такое применение возвращает новую функцию, которая уже принимает следующий аргумент.
Чистая функция
«Чистая функция» - это функция, входные параметры которой объявляются как входы, и ни один из них не может быть скрыт, а результаты объявляются как выходы.
Чистые функции работают со своими параметрами. Это не очень эффективно, когда функция ничего не возвращает. Кроме того, они выдают один и тот же результат для заданных параметров.
Пример:
Function Pure(a,b)
{
return a+b;
}
Функции с побочным эффектом
Функции с побочным эффектом работают прямо противоположно тому, как работают чистые функции. У них есть скрытые входы и выходы; это и называется «с побочным эффектом». Функции с побочным эффектом нельзя использовать и тестировать в изолированной среде, так как у них есть зависимости.
Пример:
int z;
function notPure(){
z = z+10;
}
Композиция функций
Композиция функций – это объединение двух или более функций с целью создать одну.
Разделяемые состояния
Разделяемые состояния – это немаловажная концепция в ООП. Попросту говоря, это добавление свойств к объекту. Например, если «Жесткий диск» является объектом, то «Емкость запоминающего устройства» и «Размер диска» можно добавить в качестве свойств.
Побочные эффекты
Побочные эффекты – это любые изменения состояния, которые происходят вне функции, которую мы вызвали. Самая главная цель ФП – минимизировать количество побочных эффектов, изолировав их от остального программного кода. Для функционального программирования важно, чтобы в остальной логике программы побочных эффектов не было.
Преимущества функционального программирования
- Позволяет избежать ошибок и проблем в коде, которые сбивают в толку
- ФП-код проще тестировать, для него проще выполнять модульное тестирование и отладку кода
- Параллельное выполнение и конкурентность
- Быстрое развертывание кода и устойчивость к сбоям
- Предлагает лучший модульный принцип организации с более коротким кодом
- Повышенная продуктивность разработчиков
- Поддерживает вложенные функции
- Конструкции функционального программирование, такие как Lazy Map и Lazy List и т.д.
- Позволяет эффективно использовать лямбда-исчисление
Недостатки функционального программирования
- Парадигма функционального программирования не так уж проста, так что в ней трудно будет разобраться новичку
- Программы трудны в сопровождении, поскольку очень много объектов дорабатываются в процессе написания кода
- Требуются частые замены реализации объекта имитированной реализацией, а также серьезная настройка системной среды
- Повторное использование достаточно затруднительно и требует постоянной реорганизации исходного кода
- Объекты могут некорректно моделировать задачу
Сравнение функционального программирования и объектно-ориентированного программирования
Функциональное программирование |
ООП |
ФП использует неизменяемые данные |
ООП использует изменяемые данные |
Придерживается модели декларативного программирования |
Придерживается модели императивного программирования |
Фокусируется на том, что вы делаете в программе |
Фокусируется на том, как вы пишете код |
Поддерживает параллельное программирование |
Не поддерживает параллельное программирование |
У его функций нет побочных эффектов |
Функции могут выдавать много побочных эффектов |
Управление потоками выполняется путем вызовов функций с рекурсией и без нее |
Управление потоками выполняется с помощью циклов и условных операторов |
Порядок выполнения операторов не важен |
Порядок выполнения операторов важен |
Поддерживает как абстракцию данных, так и абстракцию поведения |
Поддерживает только абстракцию данных |
Заключение
- Функциональное программирование, или ФП, - это своего рода философия создания программного обеспечения, которая основана на некоторых фундаментальных определяющих принципах
- Концепции функционального программирования делают уклон в сторону результатов, а не самого процесса
- Цель любого ФП-языка – имитация математических функций
- Некоторые самые известные языки функционального программирования: 1) Haskell; 2) SM; 3) Clojure; 4) Scala; 5) Erlang; 6) Clean
- «Чистая функция» - это функция, входные параметры которой объявлены как входы, и ни один из них не должен быть скрыт, а результаты объявлены как выходы
- Неизменяемость данных подразумевает то, что вы должны просто создавать новые структуры данных вместо того, чтобы менять уже существующие
- Позволяет избежать проблем и ошибок в коде, которые сбивают с толку
- Функциональный код не так прост, поэтому новичку будет сложно его понять
- ФП использует неизменяемые данные, а ООП – изменяемые