Обязательно изучите функциональное программирование в 2017 году

Перевод статьи Allan MacGregor: You Should Learn Functional Programming in 2017.

Функциональное программирование существует уже очень давно, начиная с появления языка программирования Lisp в 50-х годах прошлого века. И, если вы заметили, на протяжении последних двух лет такие языки, как Clojure, Scala, Erlang, Haskell и Elixir, создают много шума и привлекают к себе внимание.

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

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

Как мы уже говорили, функциональное программирование берет свое начало еще в 50-х годах с момента создания Lisp для работы в серии научных компьютеров IBM700/7000. Lisp представил множество парадигм и особенностей, которые теперь мы связываем с функциональным программированием, и хотя мы можем назвать Lisp дедушкой функционального программирования мы можем копнуть глубже и взглянуть на еще большую общность между всеми функциональными языками программирования — лямбда-исчисление.

Это, безусловно, самый интересный аспект функционального программирования. Все языки функционального программирования основаны на одной и той же простой математической основе — лямбда-исчислении.

Лямбда-исчисление обладает свойством полноты по Тьюрингу, то есть является универсальной моделью вычислений, которая может быть использована для моделирования любой одноленточной машины Тьюринга. Ее тезка, греческая буква лямбда (λ), используется в лямбда-выражениях и лямбда-условиях для обозначения связывания переменной с функцией. — Википедия

Лямбда-исчисление — удивительно простая, но мощная концепция. В основе лямбда-исчисления лежат два понятия:

  • Функциональная абстракция, использующаяся для обобщения выражений посредством введения имен (переменных)
  • Функциональное применение, которое используется для вычисления обобщенных выражений путем присвоения переданных имен к определенным значениям

В качестве примера давайте рассмотрим функцию f с одним аргументом, увеличивающую аргумент на единицу:

f = λ x. х + 1

Допустим, мы хотим применить функцию к числу 5. Тогда функцию можно читать следующим образом:

f(5) => 5 + 1

Основы функционального программирования

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

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

В функциональных языках функции являются объектами первого класса. Это означает, что функция может храниться в переменной. Например, в Elixir это так:

double = fn(x) -> x * 2 end

Затем мы легко можем вызвать эту функцию:

double.(2)

Функции высшего порядка

Функции высшего порядка — функции, принимающие одну или несколько функций в качестве аргументов и/или возвращающие новую функцию. Для демонстрации концепции давайте снова воспользуемся нашей функцией double:

double = fn(x) -> x * 2 end
Enum.map(1..10, double)

В этом примере Enum.map в качестве первого аргумента принимает перечисляемый - список, а в качестве второго - функцию, которую мы только что определили. Затем Enum.map применяет функцию к каждому элементу списка. В результате мы получаем:

[2,4,6,8,10,12,14,16,18,20]

Неизменяемое состояние

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

Как и прежде, давайте воспользуемся Elixir для иллюстрации:

iex> tuple = {:ok, "hello"}
{:ok, "hello"}
iex> put_elem(tuple, 1, "world")
{:ok, "world"}
iex> tuple
{:ok, "hello"}

В примере выше наша переменная tuple никогда не изменит своего значения. В третьей строке put_elemвозвращает совершенно новый tuple без изменения значения оригинала.


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

  • Функциональное программирование существует уже давно (с начала 50-х годов)
  • Функциональное программирование основано на математических концепциях, в частности на лямбда-исчислениях
  • Функциональное программирование считалось слишком медленным по сравнению с императивными языками
  • Функциональное программирование возвращается

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

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

Объектно-ориентированное программирование уже не справляется, особенно когда речь идет о конкурентности и параллелизме. Попытки добавить их к этим языкам, добавляют много сложностей и чаще всего приводят к чрезмерному усложнению и низкой производительности.

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

Но не надо верить мне на слово, вы можете найти достаточно доказательств, посмотрев на технологические новости стартапов, таких как WhatsApp и Discord:

  • 900 миллионов пользователей WhatsApp поддерживают всего лишь 50 инженеров, используя Erlang
  • Discord подобным образом обрабатывают более миллиона запросов в минуту с использованием Elixir

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

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


Слушайте наш подкаст в iTunes и SoundCloud, читайте нас на Medium, контрибьютьте на GitHub, общайтесь в группе Telegram, следите в Twitter и канале Telegram, рекомендуйте в VK и Facebook.

Статья на GitHub