В программировании часто используется термин "парадигма".
Паради́гма программи́рования — это совокупность идей и понятий, определяющих стиль написания компьютерных программ (подход к программированию). Это способ концептуализации, определяющий организацию вычислений и структурирование работы, выполняемой компьютером. (Wikipedia)
Парадигма — это больше, чем просто другой алгоритм решения задачи. Как правило, структура кода при использовании разных парадигм отличается очень значительно и требует знаний, выходящих за рамки только синтаксиса языка (например, автоматное программирование требует хотя бы базового понимания теории автоматов). Причём подавляющее большинство современных (и не очень) языков программирования являются мультипарадигменными и позволяют писать код, используя множество стилей. Иногда эти стили взаимоисключающие, иногда они дополняют друг друга. К текущему моменту мы писали код, используя две парадигмы: императивную и декларативную.
Императивная парадигма
Императивная парадигма — стиль написания кода в виде набора последовательных инструкций (команд) с активным использованием переменных. Возможно, данное определение звучит страшно, но на практике императивный стиль является доминирующим. Не считая этого курса, весь остальной код мы писали именно в императивном стиле.
# Поиск максимального числа
numbers = [10, 20, 52, 105, 56, 89, 96]
max_num = numbers[0]
for number in numbers:
if number > max_num:
max_num = number
print(max_num) # => 105
В императивном стиле широко используется присваивание (а значит, и переменные) и циклы. Эта парадигма популярна потому, что она в точности соответствует тому, как работает компьютер: последовательно выполняет инструкции и использует память для хранения промежуточных результатов. Обычно говорят, что императивная программа отвечает на вопрос КАК («как достичь нужного результата»).
Python, впрочем, как и Java/Ruby/JavaScript/C#/Perl/PHP/Go, относится к императивным языкам. То есть языкам, в которых доминирующей является императивная парадигма (язык толкает к её использованию). Что, однако, не мешает использовать и другие парадигмы в рамках этих языков.
Декларативная парадигма
Императивному стилю противопоставляют декларативный, который нередко называют функциональным. Ключевое отличие функционального стиля от императивного в том, что при таком стиле программа выглядит как спецификация (которая может быть очень сложной), а не как набор инструкций. То есть программа отвечает на вопрос ЧТО («что мы хотим получить»). Эту грань довольно трудно уловить сразу, но, например, вся математика, по своей сути, декларативна.
# Поиск максимального числа
from functools import reduce
numbers = [10, 20, 52, 105, 56, 89, 96]
max_num = reduce(lambda acc, number: number if number > acc else acc, numbers)
print(max_num) # => 105
Главное отличие декларативной парадигмы от императивной на практике — отсутствие присваивания. Вы можете мне возразить, что в коде выше определяются константы и в них сохраняются значения. Присмотритесь к коду внимательнее, вы заметите что константы создаются ровно один раз, инициализируются первоначальными значениями, которые больше не меняются (в этом смысл констант). Конструкцию, типа my_var = expression
, можно рассматривать как логическое высказывание. В математике это звучало бы так: "допустим, A — это множество чисел". Что бы мы дальше ни делали, "A" остаётся всегда тем же, чем было во время определения.
Дело в том, что в математике доказательства строятся с помощью логических цепочек. Из одних утверждений следуют другие, и таким образом мы можем прийти к решению задачи. Всё это возможно только в том случае, когда утверждения не изменяются. Иначе, следствия могут оказаться неверными уже после того, как они были получены, а значит мы не сможем рассуждать логически.
То же самое касается и acc
с number
. Эти параметры всегда определяются ровно один раз, так как каждый вызов функции при таком определении (без использования ссылок) не зависит от другого вызова. В мире функциональных языков такую операцию называют связывание. Визуально оно выглядит как присваивание, но это не оно. Попытка связать уже связанный идентификатор (в функциональных языках нет переменных) завершится ошибкой. Ниже пример на языке Erlang:
1> A = 4.
4
2> A = 'hey'.
** exception error: no match of right hand side value hey
Отсутствие присваивания автоматически означает то, что в функциональной парадигме невозможно использование циклов. Вместо них используется рекурсия. Другой важной особенностью функционального стиля считается активное использование функций как объектов первого рода. В основном в функциях высшего порядка. Причём они способны заменить рекурсию в подавляющем большинстве задач, в чем мы уже убедились в предыдущих уроках (убедились так, что даже не рассматривали рекурсию). Любая задача из представленных решалась основной тройкой функций высшего порядка.
Языков, использующих декларативную парадигму, довольно много. Они, в своей массе, менее популярны, чем императивные, но прочно занимают определённые ниши и активно используются в промышленном программировании. К таким языкам относятся: Haskell/Erlang/Elixir/OCaml/F#. В этих языках нет присваивания и циклов. Императивный код на них написать просто невозможно. Немного особняком стоят такие языки, как Scala и Clojure (и другие из семейства LISP). В этих языках основная парадигма — декларативная, и язык толкает к тому, чтобы писать в таком стиле, но при необходимости на них можно написать самый настоящий императивный код с присваиванием и циклами. А вот почти все императивные языки позволяют писать декларативно. Причём, если одни языки имеют довольно слабую поддержку декларативной парадигмы, то другие настолько мощную, что в них можно писать только декларативно.
Другие парадигмы
Большинство других парадигм являются разновидностями функциональной или императивной парадигм. Из наиболее значимых выделяют следующие:
- Логическое программирование
- Автоматное программирование
- Объектно-ориентированное программирование
- Метапрограммирование
Дополнительные материалы
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты
- Статья «Как учиться и справляться с негативными мыслями»
- Статья «Ловушки обучения»
- Статья «Сложные простые задачи по программированию»
- Вебинар «Как самостоятельно учиться»
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.