Рубріки: Теория

Функциональное программирование: код без проблем и ошибок

Ольга Змерзла

Функциональное программирование (FP) долгое время оставалось нишевым явлением. Однако теперь многие языки (Java и Python в их числе) все чаще стали перенимать его концепции. 

Самая важная задача FP — сделать код понятнее. Такой тип программирования по своей природе прекрасно подходит для машинного обучения и анализа данных.

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

Функциональное программирование VS объектно-ориентированное программирование

Функциональное программирование Объектно-ориентированное программирование
Использование неизменяемых данных. Использование изменяемых данных.
В функциях нет побочных эффектов. Может иметь большое количество побочных эффектов.
Порядок выполнения функций не имеет значения. Порядок выполнения имеет значения.
Поддержка абстракции данных и абстракции поведения. Поддержка абстракции данных.
Для управления потоком используются вызовы функций и вызовы функций с рекурсией. Для управления потоком используются условные операторы и циклы.
Поддержка параллелизма. Без поддержки параллелизма.
Осуществляется в рамках декларативного программирования. Осуществляется в рамках императивного программирования.

Смысл FP заключается в описании взаимодействий между командами и подпрограммами. Здесь не задаются последовательности этих команд, а весь код состоит из правил работы с данными. 

Функциональное программирование:

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

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

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

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

Функцию можно назвать чистой, если:

  • при ее выполнении не появляются побочные эффекты (скрытый ввод-вывод или неявные входы-выходы);
  • она всегда отдает одно значение при одних и тех же вызываемых аргументах.

Почему чистые функции в приоритете?

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

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

Обязательное требование в функциональном программировании — использование функций первого класса и высшего порядка. 

Функции первого класса являются переменными первого класса. Эти переменные передаются функциям в виде параметров. Они сохраняются в структуре данных или могут быть возвращены из функций.

Функции высшего порядка также могут возвращать функции или принимать другие в качестве аргументов.

Например:

show_output(f)            // function show_output is declared taking argument f 

                          // which are another function

    f();                  // calling passed function


print_gfg()             // declaring another function 

    print("hello gfg");


show_output(print_gfg)  // passing function in another function

Концепция высшего порядка применяется к функциям в целом, а функции первого порядка касаются функций в языках программирования.

Часто функции высшего порядка применяются для:

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

Неизменяемые переменные

Функциональное программирование не предусматривает изменение переменных после инициализации. Несмотря на то, что у нас есть возможность создания новых переменных, уже существующие изменить нельзя. Такой подход помогает поддерживать состояние программы в течение всего времени ее выполнения. Установив значение вновь созданной переменной, можно быть уверенным, что ее значение уже никогда не изменится.

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

Неизменяемость полезна для потокобезопасности кода (thread-safety).

Ссылочная прозрачность

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

Ссылочная прозрачность имеет важное значение, поскольку поддается кэшированию.

Например: пусть создаваемая функция square() возвращает результат умножения числа самого на себя:

function square(n) {

  return n * n;

}

Функция является чистой, а потому для одного и того же значения на входе возвращает одно и то же значение на выходе:

square(2); // 4

square(2); // 4

square(2); // 4

// ...

Сколько бы функции не передавалось 2, она будет всегда возвращать число 4. Получается, что square(2) можно заменить 4 — это означает, что функция имеет ссылочную прозрачность.

Функциональное программирование и лямбда-исчисления

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

Лямбда-исчисление состоит из трех элементов:

  • функции;
  • переменные;
  • применение функций к переменным.

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

Принципы лямбда-исчисления, формирующие функциональное программирование:

  • Прохождение всех функций через процесс каррирования — выполнение функции с несколькими аргументами. Сначала — с первым аргументом, в результате чего будет возвращена новая функция с набором аргументов на один меньше. Рекурсия (повторение) будет продолжаться, пока не будут использованы все аргументы функции.
  • Все функции являются анонимными, значение имеет список аргументов.

В заключение

Хотя разобраться в функциональном программировании не так уж и просто, его популярность набирает обороты.

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

  • Простое тестирование и отладка. Это возможно благодаря чистым функциям, которые используют неизменяемые значения, принимают аргументы и осуществляют выводы. С их помощью становится намного проще разрешать проблемы, возникающие в программе.
  • Ленивая оценка. Значение оценивается и сохраняется только в случае необходимости. Нет необходимости полной повторной оценки.
  • Применение и реализация параллелизма. Функциональное программирование полезно для реализации параллелизма. Это возможно благодаря чистым функциям, которые не вносят никаких изменений в данные и переменные.
  • Способность обрабатывать функции как значения. Значения передаются функциям в качестве параметров — от такой реализации код становится читаемым, простым и понятным.
  • Простота понимания чистых функций. Чистые функции зависят только от входных данных, они не меняют значения и состояния программы. Каким бы ни был результат, они возвращают изначальное значение.
  • Ориентирование на результаты, а не процесс. Важный момент в программировании — получение удобоваримого конечного результата.
  • Неизменяемые данные. Это значит, что можно легко создавать структуры данных и при этом не изменять уже существующие.

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

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

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

Останні статті

Обучение Power BI – какие онлайн курсы аналитики выбрать

Сегодня мы поговорим о том, как выбрать лучшие курсы Power BI в Украине, особенно для…

13.01.2024

Work.ua назвал самые конкурентные вакансии в IТ за 2023 год

В 2023 году во всех крупнейших регионах конкуренция за вакансию выросла на 5–12%. Не исключением…

08.12.2023

Украинская IT-рекрутерка создала бесплатный трекер поиска работы

Unicorn Hunter/Talent Manager Лина Калиш создала бесплатный трекер поиска работы в Notion, систематизирующий все этапы…

07.12.2023

Mate academy отправит работников в 10-дневный оплачиваемый отпуск

Edtech-стартап Mate academy принял решение отправить своих работников в десятидневный отпуск – с 25 декабря…

07.12.2023

Переписки, фото, история браузера: киевский программист зарабатывал на шпионаже

Служба безопасности Украины задержала в Киеве 46-летнего программиста, который за деньги устанавливал шпионские программы и…

07.12.2023

Как вырасти до сеньйора? Девелопер создал популярную подборку на Github

IT-специалист Джордан Катлер создал и выложил на Github подборку разнообразных ресурсов, которые помогут достичь уровня…

07.12.2023