Перевод статьи 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.