Парадигмы программирования. Эпизод III: Функциональное программирование

Парадигмы программирования. Эпизод III: Функциональное программирование

Больше вкусностей найдешь на моем канале - https://t.me/emotional_robot


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

Функция в императивном подходе

В данной статье я постарался на конкретных примерах объяснить, чем отличается императивный подход в программировании от декларативного. Затем в статье о процедурном программировании рассказал об особом виде подпрограмм, помогающих лучше организовать код - процедуры. Процедура принимает некоторые параметры (аргументы), которые помогают ей в различных вычислениях и операциях (ввода/вывода, вызова других процедур и так далее).

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


Че началось-то опять?

Спокойно, щас на примере покажу, че почем. Все же знают операцию сложения двух чисел? Надо взять первое число, прибавить к нему второе - получится третье число:

1 + 2 = 3

Для реализации операции суммы двух чисел на языке программирования JavaScript (ну на чем еще, я ж фронтендер) мы напишем такую функцию:

function sum(a, b) {

return a + b;

}

То есть, отличие от процедур только в ключевом слове "function" (в других языках это могут быть слова "func", "fun") и в слове "return", после которого должен быть возвращен результат выполнения функции. В данном случае, вернется результат сложения аргументов "a" и "b". Но куда этот результат вернется?

Да куда угодно, в большинстве случаев, в какую-нибудь переменную:

let result = sum(1, 2);

Мы объявили переменную "result" с помощью ключевого слова "let", и поместили в нее число "3" - результат вычисления функции sum(1, 2).

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

Функция в декларативном подходе


Помните из математики такую запись?


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

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

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

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

Улавливаете суть? Одни и те же элементы первого множества по определенному правилу можно однозначно соотнести с элементами другого множества. Никак иначе. Нельзя вызвать функцию два раза с одинаковыми аргументами и получить два разных результата. Это основа функционального программирования.

Функция как раз является тем самым правилом, по которому одни элементы преобразуются в другие:

y = f(x)

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

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

И шо нам это дает?

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

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

Итого

Есть языки, поддерживающие объектно-ориентированный стиль, и языки, поддерживающие функциональный стиль. До кучи есть мультипарадигмальные языки программирования, на которых можно писать и в объектно-ориентированном, и в функциональном стиле (например, JavaScript). И весь этот зоопарк ЯПов новичка может свести с ума. Как выбрать, на чем писать? По каким параметрам выбирать язык? Что легче? Что интереснее? За знание какого языка больше платят? Кто здесь? Где мой конь?

Я бы при всем желании не смог наставить на верный путь, если не объяснить заранее все концепции и подходы в программировании. Да, можете себе представить, что вся эта вакханалия была лишь подготовкой к нормальным советам? Так и живем.

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


Но не волнуйтесь, это деление гораздо проще для понимания, чем парадигмы программирования. Но не менее интересное.



Report Page