Функциональное программирование представляет одну из парадигм программирования, которая базируется на следующих принципах:
Функции представляют полноценные объекты ("first-class objects", "first-class citizens"). Это означает, что переменным можно присваивать также, как и другие объекты и примитивные значения; функции можно использовать в качестве аргументов других функций или в качестве их возвращаемого значения.
Функции работают с неизменяемыми структурами данных. Структуры данных в функциональном программировании обычно неизменяемы или не изменяются. Операции же, которые выполняются над структурами данных, при необходимости создают новые структуры данных и возвращают их в качестве результатов. Например, в чисто функциональных языках программирования после создания списков или других структур данных их нельзя изменить
Функции не имеют побочных эффектов. В функциональном программировании функции обычно вообще не имеют побочных эффектов и ведут себя скорее как математические функции. Это означает, что функции в функциональном программировании всегда возвращают один и тот же результат для одних и тех же входных данных и не вызывают никаких побочных эффектов. В чисто функциональных языках побочные эффекты уже предотвращаются самим языком.
Функциональные программы применяют декларативный стиль программирования. Императивное программирование — это парадигма программирования, в которой компьютеру даются очень точные индивидуальные инструкции о том, как решить проблему. В императивных программах используются явные операторы цикла (циклы while, for и т. д.), условные операторы (if-else) и их последовательности. Функциональные же программы исповедуют декларативный стиль, что означает, что программа больше говорит, что следует делать, а не как. В результате функциональные программы обычно более читабельны, более содержательны и более компактны, чем эквивалентный императивный код.
Различные языки могут не быть чисто функциональными, но тем не менее могут поддерживать функциональную парадигму. К примеру, возьмем JavaScript, который не является чистым функциональным языком, однако позволяет писать в функциональном стиле. Рассмотрим следующую программу перебора массива на JavaScript:
// набор объектов для перебора const people = [ {name: "Tom", age:38}, {name: "Kate", age:31}, {name: "Bob", age:42}, {name: "Alice", age:34}, {name: "Sam", age:25} ]; // перебор объектов массива for(let i = 0; i < people.length; i++){ console.log(people[i].name); }
Данный код предназначен для вывода каждого значения массива. Это то, что должно произойти. Однако на самом деле код больше ориентирован на то, как все это должно работать: инициализировать переменную счетчика, проверить условие завершения, обратиться к элементу массива по определенному индексу, а затем увеличить переменную счетчика.
Таким образом, императивные программы содержат много лишнего кода (шаблонного кода), что уменьшает читабельность программы и раздувает ее. Конечно, если говорить о выше приведенном коде, который предельно прост, в нем несложно ориентироваться, однако если приходится сталкиваться глубокой вложенностью циклов и условных конструкций, то в программе можно потеряться.
Используя функциональное программирование, проблемы зачастую можно сформулировать гораздо более читабельным образом. Например, для данной задачи гораздо более подходит метод forEach(), который перебирает элементы массива и в качестве параметра получает функцию обратного вызова. Функция обратного вызова получает текущий перебираемый элемент массива и выполняет для него некоторые действия:
// набор объектов для перебора const people = [ {name: "Tom", age:38}, {name: "Kate", age:31}, {name: "Bob", age:42}, {name: "Alice", age:34}, {name: "Sam", age:25} ]; const printName = (p)=>console.log(p.name); people.forEach(printName);
И хотя функциональный код не обязательно короче по количеству строк, он уже намного читабельнее. В отличие от императивного варианта, теперь основное внимание уделяется логике программы (что делает программа), а не самому циклу (как делает).