Принципы функционального программирования: почему это важно

Рассказываем о принципах функционального программирования: какие у него минусы, и какие языки относятся к функциональным.

Основные концепции

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

Чистые функции

Чистая функция максимально проста. Она должна всегда возвращать один и тот же результат. Посмотрите на эту JavaScript-функцию:

var z = 10;

function add(x, y) {
  return x + y;
}

Конечно, это искусственный пример, но он очень хорошо демонстрирует, как должна работать чистая функция. При одних и тех же значениях x и y мы всегда будем получать одинаковый результат функции. Предсказуемость – важная часть работы программы в функциональном программировании.

Изменяемые данные и побочные эффекты

Вернемся к примеру кода. Если мы добавим в качестве аргумента функции add(), переменную z, которая объявлена выше, наша функция перестанет быть чистой и предсказуемой. Почему? Потому что z объявлена как обычная переменная: она доступна для изменения из любого места программы.

Идея неизменности в функциональном программировании заключается в том, что переменные не могут быть изменены после объявления.

Корректный код чистой функции с z должен выглядеть так:

const x = 10;
const z = 10;

add (x, z); // вернет 20

В этом случае функция всегда будет возвращать предсказуемый результат. Если функция не будет работать предсказуемо – это приведет к нежелательным побочным эффектам.

Еще один пример не функционального кода – классические циклы. Вспомним, как выглядит типичный цикл for в JavaScript:

var acc = 0;

for (var i = 1; i <= 10; ++i) {
  acc += i;
}

console.log(acc); // выведет 55

Первое, на что нужно обратить внимание, – то, что цикл использует var i для подсчета шагов. В функциональном программировании использование такого цикла неприемлемо, так как это может привести к непредсказуемому поведению цикла.

Чтобы избежать побочных эффектов, в ФП для создания циклов используются рекурсивные функции.

function sumRange(start, end, acc) {
  if (start > end) {
    return acc;
  } else {
    return sumRange(start + 1, end, acc + start);
  }
}

console.log(sumRange(1, 10, 0)); // выведет 55

Такая конструкция позволяет использовать константы для определения начала, конца цикла и шага. В основе такого типа цикла лежит идея вызова функции внутри себя, или рекурсивного вызова. В примере выше функция sumRange() с заданными аргументами делает проверку условия, и в случае ложного результата вызывает саму себя с измененными аргументами.

Композиция функций

Композиция функций – это подход в функциональном программировании, который подразумевает вызов одних функций в качестве аргументов других, для создания сложных составных функций из более простых.

function addOne(x) {
  return x + 1;
}

function timesTwo(x) {
  return x * 2;
}

console.log(addOne(timesTwo(3))); // выведет 7
console.log(timesTwo(addOne(3))); // выведет 8

В примере выше мы описали две простые функции: addOne (прибавляет к аргументу единицу) и timesTwo (умножает аргумент на два). Техника компоновки позволяет нам вызывать две эти функции друг в друге в разном порядке. В результате, с разным логическим порядком вызова чистых функций и одинаковым значением аргумента мы получили более сложный функционал, который дает нам необходимый результат и делает это предсказуемо.

Польза функционального программирования

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

Недостатки функционального программирования

Функциональное программирование плохо подходит для алгоритмов, основанных на графах из-за сравнительно более медленной работы программы. ФП в целом плохо применимо в решениях, которые годами основывались на использовании императивного подхода.

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

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

Так как функциональное программирование – это прежде всего подход к написанию кода, использовать его принципы можно в любом языке. Однако существуют языки, специально заточенные под функциональный подход. Первый и самый известный из них – Lisp. Он появился еще в 1958 году. Его автор – Джон Маккарти, информатик и автор термина «искусственный интеллект». Lisp по сей день популярен в среде проектировщиков ИИ.

Более современные функциональные языки, такие как Elm и Elixir, по данным GitHub и Stack Overflow постепенно и уверенно набирают популярность. Рост популярности JavaScript также привел к повышенному интересу к концепциям функционального программирования для применения в этом языке.

Будет полезно:

ЛУЧШИЕ СТАТЬИ ПО ТЕМЕ

admin
30 июня 2018

Шаблоны проектирования в Python: для стильного кода

Многие шаблоны проектирования встроены в Python из коробки, а другие очень ...