В программировании есть два больших подхода — императивное и функциональное. Они существенно отличаются логикой работы, ещё и создают путаницу в названиях. Сейчас объясним.
Функциональное — это про функции?
❌ Нет. Функциональное — это не про функции. Функции есть почти в любых языках программирования: и в функциональных, и в императивных. Отличие функционального программирования от императивного — в общем подходе.
Метафора: инструкция или книга правил
Представьте, что вы открываете кафе-столовую. Сейчас у вас там два типа сотрудников: повара и администраторы.
Для поваров вы пишете чёткие пошаговые инструкции для каждого блюда. Например:
- Налить воды в кастрюлю
- Поставить кастрюлю с водой на огонь
- Добавить в кастрюлю с водой столько-то соли
- Если нужно приготовить 10 порций, взять одну свёклу. Если нужно приготовить 20 порций, взять две свёклы.
- Почистить всю свёклу, которую вы взяли
- …
Повар должен следовать этим инструкциям ровно в той последовательности, в которой вы их написали. Нельзя сначала почистить свёклу, а потом взять её. Нельзя посолить кастрюлю, в которой нет воды. Порядок действий важен и определяется вами. Это пример императивного программирования. Вы повелеваете исполнителем.
Ликбез программиста #1: Парадигмы программирования — ООП, ФП…
Можно сказать, что исполнители выполняют ваши задания.
Для администратора вы пишете не инструкцию, а как бы книгу правил:
- У нас нельзя со своим. Если гости пришли со своим, то сделать им замечание такое-то.
- В зале должно быть чисто. Если в зале грязно, вызвать уборщика.
- Если образовалась очередь, открыть дополнительную кассу.
Это тоже команды, но исполнять их администратор будет не в этой последовательности, а в любой на своё усмотрение. Можно сказать, что задача этого человека — исполнять функции администратора, и мы описали правила, по которым эти функции исполнять. Это пример функционального программирования.
❌ Программисты, не бомбите
Конечно же, это упрощено для понимания. Вы сами попробуйте это нормально объяснить (можно прямо в комментах).
Императивное программирование
Примеры языков: C, С++, Go, Pascal, Java, Python, Ruby
Императивное программирование устроено так:
В языке есть команды, которые этот язык может выполнять. Эти команды можно собрать в подпрограммы, чтобы автоматизировать некоторые однотипные вычисления. В каком порядке записаны команды внутри подпрограммы, в том же порядке они и будут выполняться.
Есть переменные, которые могут хранить данные и изменяться во время работы программы. Переменная — это ячейка для данных. Мы можем создать переменную нужного нам типа, положить туда какое-то значение, а потом поменять его на другое.
Если подпрограмме на вход подать какое-то значение, то результат будет зависеть не только от исходных данных, но и от других переменных. Например, у нас есть функция, которая возвращает размер скидки при покупке в онлайн-магазине. Мы добавляем в корзину товар стоимостью 1000 ₽, а функция должна нам вернуть размер получившейся скидки. Но если скидка зависит от дня недели, то функция сначала проверит, какой сегодня день, потом посмотрит по таблице, какая сегодня скидка.
Вафлеративное программирование
Получается, что в разные дни функция получает на вход 1000 ₽, но возвращает разные значения — так работает императивное программирование, когда всё зависит от других переменных.
Последовательность выполнения подпрограмм регулируется программистом. Он задаёт нужные условия, по которым движется программа. Вся логика полностью продумывается программистом — как он скажет, так и будет. Это значит, что разработчик может точно предсказать, в какой момент какой кусок кода выполнится — код получается предсказуемым, с понятной логикой работы.
Если у нас код, который считает скидку, должен вызываться только при финальном оформлении заказа, то он выполнится именно в этот момент. Он не посчитает скидку заранее и не пропустит момент оформления.
Суть императивного программирования в том, что программист описывает чёткие шаги, которые должны привести код к нужной цели.
Звучит логично, и большинство программистов привыкли именно к такому поведению кода. Но функциональное программирование работает совершенно иначе.
Функциональное программирование
Примеры языков: Haskell, Lisp, Erlang, Clojure, F#
Смысл функционального программирования в том, что мы задаём не последовательность нужных нам команд, а описываем взаимодействие между ними и подпрограммами. Это похоже на то, как работают объекты в объектно-ориентированном программировании, только здесь это реализуется на уровне всей программы.
Например, в ООП нужно задать объекты и правила их взаимодействия между собой, но также можно и написать просто код, который не привязан к объектам. Он как бы стоит в стороне и влияет на работу программы в целом — отправляет одни объекты взаимодействовать с другими, обрабатывает какие-то результаты и так далее.
Функциональное программирование здесь идёт ещё дальше. В нём весь код — это правила работы с данными. Вы просто задаёте нужные правила, а код сам разбирается, как их применять.
Если мы сравним принципы функционального подхода с императивным, то единственное, что совпадёт, — и там, и там есть команды, которые язык может выполнять. Всё остальное — разное.
Команды можно собирать в подпрограммы, но их последовательность не имеет значения. Нет разницы, в каком порядке вы напишете подпрограммы — это же просто правила, а правила применяются тогда, когда нужно, а не когда про них сказали.
Переменных нет. Вернее, они есть, но не в том виде, к которому мы привыкли. В функциональном языке мы можем объявить переменную только один раз, и после этого значение переменной измениться не может. Это как константы — записали и всё, теперь можно только прочитать. Сами же промежуточные результаты хранятся в функциях — обратившись к нужной, вы всегда получите искомый результат.
Функции всегда возвращают одно и то же значение, если на вход поступают одни и те же данные. Если в прошлом примере мы отдавали в функцию сумму в 1000 ₽, а на выходе получали скидку в зависимости от дня недели, то в функциональном программировании если функция получит в качестве параметра 1000 ₽, то она всегда вернёт одну и ту же скидку независимо от других переменных.
Можно провести аналогию с математикой и синусами: синус 90 градусов всегда равен единице, в какой бы момент мы его ни посчитали или какие бы углы у нас ещё ни были в задаче. То же самое и здесь — всё предсказуемо и зависит только от входных параметров.
Последовательность выполнения подпрограмм определяет сам код и компилятор, а не программист. Каждая команда — это какое-то правило, поэтому нет разницы, когда мы запишем это правило, в начале или в конце кода. Главное, чтобы у нас это правило было, а компилятор сам разберётся, в какой момент его применять.
В русском языке всё работает точно так же: есть правила правописания и грамматики. Нам неважно, в каком порядке мы их изучили, главное — чтобы мы их вовремя применяли при написании текста или в устной речи. Например, мы можем сначала пройти правило «жи-ши», а потом правило про «не с глаголами», но применять мы их будем в том порядке, какой требуется в тексте.
Получается, что смысл функционального программирования в том, чтобы описать не сами чёткие шаги к цели, а правила, по которым компилятор сам должен дойти до нужного результата.
Курсы по программированию с нуля
Приходите к нам в ИТ. У нас есть удаленная работа, высокие зарплаты и удобное обучение в «Яндекс Практикуме». Старт бесплатно.
Получите ИТ-профессию
В «Яндекс Практикуме» можно стать разработчиком, тестировщиком, аналитиком и менеджером цифровых продуктов. Первая часть обучения всегда бесплатная, чтобы попробовать и найти то, что вам по душе. Дальше — программы трудоустройства.
Еще по теме
Что такое бэкап, зачем он нужен и как его делать
Каждый разработчик однажды ЛИШИЛСЯ ВСЕГО, потому что не сделал бэкап.
Что такое код-ревью
Это проверка кода на ошибки, неточности и общий стиль программирования.
Чем отличается C от C++
На 99% — ничем, но в C++ есть родная поддержка ООП.
Чем отличается C от C++
На 99% — ничем, но в C++ есть родная поддержка ООП.
Что такое исключения в программировании
Рассказ об ошибках, которые можно предусмотреть заранее.
Что такое абсолютный и относительный путь к файлу
И когда нужен каждый из них
Что такое технический долг
Фраза из лексикона сильных профессионалов
Откуда на сайтах появляется реклама, которой там не было
Всё дело в незащищённом HTTP-трафике
Что такое эмулятор
Ваш пропуск в мир винтажных приставок и хакерских игрушек
Источник: thecode.media
Функциональное программирование на Python. Часть 1. Общие вопросы
Функциональное программирование является интересной парадигмой, которая поможет по-новому взглянуть на процесс разработки и, несомненно, расширит ваш опыт новыми идеями и подходами.
- Парадигмы программирования
- В чем суть функционального программирования?
- Примеры работы в функциональном стиле
- Функции, как объекты первого класса
- Рекурсия
- Функции высшего порядка
- Чистые функции
Парадигмы программирования
Для начала обратимся к википедии за определением понятия “парадигма программирования”. Парадигма программирования — это совокупность идей и понятий, определяющих стиль написания компьютерных программ (подход к программированию). Это способ концептуализации, определяющий организацию вычислений и структурирование работы, выполняемой компьютером.
Выделяют две крупные парадигмы программирования: императивная и декларативная .
Императивное программирование предполагает ответ на вопрос “Как?”. В рамках этой парадигмы вы задаете последовательность действий, которые нужно выполнить, для того чтобы получить результат. Результат выполнения сохраняется в ячейках памяти, к которым можно обратиться в последствии.
Декларативное программирование предполагает ответ на вопрос “Что?”. Здесь вы описываете задачу, даете спецификацию, говорите, что вы хотите получить в результате выполнения программы, но не определяете, как этот ответ будет получен.
Каждая из этих парадигм включает в себя более специфические модели. В промышленности наибольшее распространение получили структурное и объектно-ориентированное программирование из группы “императивное программирование” и функциональное программирование из группы “декларативное программирование”.
В рамках структурного подхода к программированию основное внимание сосредоточено на декомпозиции – разбиении программы/задачи на отдельные блоки / подзадачи. Разработка ведётся пошагово, методом “сверху вниз”. Наиболее распространенным языком, который предполагает использование структурного подхода к программирования является язык C , в нем, основными строительными блоками являются функции.
В рамках объектно-ориентированного (ООП) подхода программа представляется в виде совокупности объектов, каждый из которых является экземпляром определенного класса, классы образуют иерархию наследования. ООП базируется на следующих принципах: инкапсуляция, наследование, полиморфизм, абстракция. Примерами языков, которые позволяют вести разработку в этой парадигме являются C# , Java .
В рамках функционального программирования выполнение программы – это процесс вычисления, который трактуется как вычисление значений функций в математическом понимании последних (в отличие от функций как подпрограмм в процедурном программировании). Языки, которые реализуют эту парадигму – это Haskell , Lisp .
Довольно часто бывает так, что дизайн языка позволяет использовать все перечисленные парадигмы (например Python ) или только часть из них (например, C++ ).
В чем суть функционального программирования?
Языки, которые можно отнести в функциональной парадигме обладают определенным набором свойств. Если язык не является чисто функциональным, но реализует эти свойства, то на нем можно разрабатывать, как говорят, в функциональном стиле. Свойства функционального стиля программирования:
- Функции являются объектами первого класса ( First Class Object ). Это означает, что с функциями вы можете работать, также как и с данными: передавать их в качестве аргументов другим функциям, присваивать переменным и т.п.
- В функциональных языках не используются переменные (как именованные ячейки памяти), т.к. там нет состояний, а т.к. нет переменных, то и нет операции присваивания, как это понимается в императивном программировании.
- Рекурсия является основным подходом для управления вычислениями, а не циклы и условные операторы.
- Используются функции высшего порядка ( High Order Functions ). Функции высшего порядка – это функций, которые могут в качестве аргументов принимать другие функции.
- Функции являются “чистыми” ( Pure Functions ) – т.е. не имеют побочных эффектов (иногда говорят: не имеют сайд-эффектов).
- Акцент на том, что должно быть вычислено, а не на том, как вычислять.
- Фокус на работе с контейнерами (хотя это спорное положение).
Python не является функциональным языком программирования, но его возможностей хватает, чтобы разрабатывать программы в функциональном стиле.
Примеры работы в функциональном стиле
Функции, как объекты первого класса
Ниже представлен код, который демонстрирует возможность Python , в части того, что функцию можно присвоить переменной и использовать ее:
>>> def mul5(value): return value*5 >>> v1 = 3 >>> f1 = mul5 >>> f1(v1) 15
Переменной f1 , в качестве значения, присваивается функция mul5 , после этого появляется возможность вызвать ее как функцию.
Рекурсия
Рекурсия – это вызов функции из нее же самой. Для начала приведем пример не рекурсивной функции, которая считает факториал:
def fact_iter(n): if n == 0 or n == 1: return 1 else: prod = 1 for i in range(1, n + 1): prod *= i return prod print(fact_iter(5))
В качестве результата получим число 120.
Перепишем ее через рекурсию:
def fact_rec(n): if n == 0 or n == 1: return 1 else: return n * fact_rec(n — 1) print(fact_rec(5))
Результат получим аналогичный первому. Заметим, что такая реализация не является эффективной по памяти, о том почему это так, и как сделать правильно см “О рекурсии и итерации“
Функции высшего порядка
Функции высшего порядка принимают в качестве аргументов другие функции. В стандартную библиотеку Python входит достаточно много таких функции, в качестве примера приведем функцию map . Она принимает функцию и список, применяет функцию к каждому элементу списка и возвращает новый модифицированный список.
>>> fn = lambda x: x**2 >>> print(list(map(fn, [1, 2, 3, 4, 5]))) [1, 4, 9, 16, 25]
Чистые функции
Чистые функции – это функции, которые не имеют побочных эффектов. В Python это не выполняется. Необходимо самостоятельно следить за тем, чтобы функция была чистой.
Например, следующая функция модифицирует данные, которые в нее передаются:
def fun_not_clear(data): if len(data) > 0: data[0] += 10 return data*2 d1 = [1, 2, 3] d2 = fun_not_clear(d1) >>> print(d1) [11, 2, 3] >>> print(d2) [11, 2, 3, 11, 2, 3]
В функцию fun_not_clear был передан массив данных, над которым был проведен ряд модификаций и сформирован новый массив. При этом исходный массив тоже был изменен. Это пример побочного эффекта, который можно получить в Python . Более корректный вариант будет выглядеть так:
def fun_clear(data): data = data[:] if len(data) > 0: data[0] += 10 return data*2 d1 = [1, 2, 3] d2 = fun_clear(d1) >>> print(d1) [1, 2, 3] >>> print(d2) [11, 2, 3, 11, 2, 3]
В следующих статьях будут более подробно описаны аспекты функционального программирования, которые можно использовать в Python . Также большое внимание уделим библиотекам, которые предоставляют инструменты, позволяющие более комфортно работать в этой парадигме.
P.S.
Вводные уроки по “Линейной алгебре на Python” вы можете найти соответствующей странице нашего сайта . Все уроки по этой теме собраны в книге “Линейная алгебра на Python”.
Если вам интересна тема анализа данных, то мы рекомендуем ознакомиться с библиотекой Pandas. Для начала вы можете познакомиться с вводными уроками. Все уроки по библиотеке Pandas собраны в книге “Pandas. Работа с данными”.
Источник: devpractice.ru
Функциональное программирование примеры программ
Комментарии
Популярные По порядку
Не удалось загрузить комментарии.
ЛУЧШИЕ СТАТЬИ ПО ТЕМЕ
16 бесплатных книг по JavaScript
Коллекция бесплатных электронных книг для тех, кто хочет изучить JavaScript. Книги предоставляются в различных цифровых форматах: PDF, EPUB, HTML и др.
Подборка материалов по HTML и CSS
В этой подборке представлены актуальные книги и видеоматериалы по HTML, CSS и верстке в целом для начинающих и продвинутых веб-разработчиков.
Изучение JavaScript с нуля
Рассказ программиста о том, как добиться успехов в изучении JavaScript.
Источник: proglib.io