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

Что означают термины функциональное, декларативное и императивное программирование?


person Community    schedule 02.03.2009    source источник
comment
Здесь есть отличные ответы. Одна интересная вещь, которая до конца не выяснена, заключается в том, что декларативный и императивный дополняют друг друга и симбиотичны, это больше, чем просто разные стили или что против как .   -  person Kit    schedule 12.10.2011
comment
@Kit Imo, некоторые ответы на этой странице объединяют термины. DP == ссылочная прозрачность (RT). DP и IP - противоположности, поэтому afaics не является дополнением целого, т.е. целая программа может быть написана в любом стиле. Вызов функции может быть либо DP (RT), либо IP, ее реализация может быть любой или смешанной. Они не являются симбиотическими в том смысле, что вызов функции IP в другой функции DP может сделать IP-адрес вызова функции DP. Они симбиотичны в том смысле, что программы реального мира (например, функционально-реактивные) могут использовать смесь, например Вызовы верхнего уровня IP в функции DP.   -  person Shelby Moore III    schedule 07.12.2011
comment
необходимо добавить в вики или ссылку на что-то похожее на вики и т. д. вот отличная ссылка в википедии en.wikipedia.org/wiki/Comparison_of_programming_paradigms   -  person Joe    schedule 26.08.2014
comment
Проголосовать за meta.stackexchange.com/a/19492 за jQuery   -  person return true    schedule 03.06.2016
comment
Этот вопрос обсуждается в Meta: meta.stackoverflow.com/q/342784/2751851   -  person duplode    schedule 02.02.2017


Ответы (14)


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

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

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

Определение декларативного выражения

Атрибут only, который может отличить декларативное выражение от императивного выражения, - это ссылочная прозрачность (RT) его подвыражений. Все остальные атрибуты либо являются общими для обоих типов выражений, либо являются производными от RT.

100% декларативный язык (то есть язык, в котором каждое возможное выражение - это RT) не допускает (среди других требований RT) изменение сохраненных значений, например HTML и большая часть Haskell.

Определение выражения RT

Часто считается, что ЛТ не имеет побочных эффектов. Термин эффекты не имеет точного определения, поэтому некоторые люди не согласны с тем, что никакие побочные эффекты не совпадают с RT. RT имеет точное определение:

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

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

Определение чистой функции

Часто говорят, что чистая функция не имеет побочных эффектов. Термин эффекты не имеет точного определения, поэтому некоторые люди с этим не согласны.

Чистые функции имеют следующие атрибуты.

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

Помните, что RT применяется к выражениям (включая вызовы функций), а чистота применяется к (реализациям) функций.

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

Производные атрибуты RT

Любой другой атрибут, указанный для декларативного программирования, например цитата из 1999 г., использованная Википедией , либо происходит от RT, либо используется в императивном программировании. Таким образом доказывается правильность моего точного определения.

Обратите внимание, неизменность внешних значений является подмножеством требований для RT.

  • В декларативных языках нет структур управления циклами, например for и while, потому что из-за неизменности условие цикла никогда не изменится.

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

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

Например, абзац HTML <p> не может быть отображен до тех пор, пока не будут вычислены подвыражения (т. Е. Теги) в абзаце. Нет изменяемого состояния, только зависимость порядка из-за логической взаимосвязи иерархии тегов (вложенность подвыражений, которые являются аналогично вложенные вызовы функций).

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

Порядок оценки

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

Например, учитывая некоторые вложенные выражения, например f( g(a, b), h(c, d) ), нетерпеливое и ленивое вычисление аргументов функции даст те же результаты, если функции f, g и h являются чистыми.

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

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

По касательной, если все идентификаторы, например a, b, c, d, неизменяемы везде, состояние, внешнее по отношению к программе, недоступно (т.е. ввод-вывод), и нет разрыва уровня абстракции, тогда функции всегда чистые.

Кстати, у Haskell другой синтаксис, f (g a b) (h c d).

Подробная информация о заказе на ознакомление

Функция - это переход состояния (не изменяемое сохраненное значение) от входа к выходу. Для RT-композиций вызовов чистых функций порядок выполнения этих переходов состояний не зависит. Переход состояния каждого вызова функции не зависит от других из-за отсутствия побочных эффектов и принципа того, что функция RT может быть заменена ее кешированное значение. Чтобы исправить популярное заблуждение, чистая монадическая композиция - это всегда декларативно и RT , несмотря на то, что монада IO в Haskell является возможно нечистой и, следовательно, обязательной по отношению к состояние World, внешнее по отношению к программе (но в смысле предупреждения ниже побочные эффекты изолированы).

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

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

По сути, все выражения являются (составом) вызовов функций, например константы - это функции без входов, унарные операторы - это функции с одним входом, двоичные инфиксные операторы - это функции с двумя входами, конструкторы - это функции, и даже управляющие операторы (например, if, for, while) могут быть смоделированы с помощью функций. Чтобы эти Функции аргумента (не путать с порядком вызова вложенных функций) оцениваются не объявляется синтаксисом, например f( g() ) может нетерпеливо оценивать g, затем f по результату g, или он может оценивать f и только лениво оценивать g, когда его результат нужен в f.

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

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

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

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

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

Например, вместо написания отдельной функции (и вместо этого используется рекурсия циклов, если функция также должна быть декларативной) для каждого из бесконечного числа возможных специализированных действий, которые могут быть применены к каждому элементу коллекции, функциональное программирование использует многократно используемые итерационные функции, например map, fold, filter. Эти итерационные функции вводят первоклассную специализированную функцию действия. Эти функции итерации выполняют итерацию по коллекции и вызывают специализированную функцию действия ввода для каждого элемента. Эти функции действий более краткие, потому что им больше не нужно содержать операторы цикла для итерации коллекции.

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

Параллелизм

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

Принцип Брента: вычисления с работой w и глубиной d могут быть реализованы в PRAM с p-процессором за время O (max (w / p, d)).

И параллелизм, и параллелизм также требуют декларативного программирования, т. Е. Неизменяемости и RT. .

Итак, откуда взялось это опасное предположение, что параллелизм == параллелизм? Это естественное следствие языков с побочными эффектами: когда у вашего языка есть побочные эффекты повсюду, то всякий раз, когда вы пытаетесь делать более одного дела за раз, вы, по сути, получаете недетерминизм, вызванный чередованием эффектов от каждой операции. . Таким образом, в языках с побочными эффектами единственный способ добиться параллелизма - это параллелизм; поэтому неудивительно, что мы часто видим их вместе.

Порядок оценки FP

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

Жадный (CBV) и ленивый (CBN) - категориальные поединки [10], потому что у них обратный порядок оценки, т. е. сначала оцениваются внешние или внутренние функции. Представьте себе перевернутое дерево, а затем нетерпеливые вычисления от ветвей дерева функций вверх по иерархии ветвей к стволу функции верхнего уровня; тогда как ленивый оценивает от ствола до кончиков веток. У нетерпеливого нет конъюнктивных продуктов (и / k / категориальных продуктов), а у ленивого нет дизъюнктивных сопутствующих продуктов (или, как / k / a категориальных сумм) [11].

Производительность

  • Жаждущий

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

Эта ненужная работа является причиной заявленного до дополнительного коэффициента log n в последовательной временной сложности нетерпеливого и ленивого как с чистыми функциями. Решение состоит в том, чтобы использовать функторы (например, списки) с ленивыми конструкторами (то есть с необязательными ленивыми продуктами), потому что с нетерпением некорректность происходит от внутренней функции. Это потому, что продукты являются конструктивными типами, т. Е. Индуктивными типами с начальной алгеброй в начальной фиксированной точке [11]

  • Ленивый

Как и в случае без завершения, ленивый слишком ленив с дизъюнктивной функциональной композицией, то есть коиндуктивная завершенность может произойти позже, чем необходимо, что приведет как к ненужной работе, так и к недетерминированию опозданий, что не происходит с нетерпеливым [10] [11]. Примерами окончательности являются исключения состояния, времени, незавершенности и времени выполнения. Это императивные побочные эффекты, но даже в чистом декларативном языке (например, Haskell) в императивной монаде ввода-вывода есть состояние (примечание: не все монады императивные!), Неявное в распределении пространства, а время - это состояние относительно императивного реальный мир. Использование ленивого режима даже с необязательным активным сопродуктом приводит к утечке лени во внутренние сопутствующие продукты, поскольку с ленивым режимом лень некорректно происходит от внешней функции (см. пример в разделе «Незавершение», где == - функция внешнего бинарного оператора). Это связано с тем, что копроизведения ограничены конечностью, т. Е. Коиндуктивными типами с конечной алгеброй на конечном объекте [11].

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

Без прекращения действия

Во время компиляции из-за проблемы остановки и взаимной рекурсии в полном языке Тьюринга, как правило, нельзя гарантировать завершение функций.

  • Жаждущий

С нетерпением, но не ленивым, для соединения Head и Tail, если Head или Tail не завершаются, то соответственно либо List( Head(), Tail() ).tail == Tail(), либо List( Head(), Tail() ).head == Head() неверно, потому что левая сторона не завершается, а правая завершается.

Тогда как ленивыми обе стороны заканчиваются. Таким образом, eager слишком увлечен конъюнктивными продуктами и не завершается (включая исключения времени выполнения) в тех случаях, когда в этом нет необходимости.

  • Ленивый

С ленивым, но не нетерпеливым, для дизъюнкции 1 или 2, если f не завершается, тогда List( f ? 1 : 2, 3 ).tail == (f ? List( 1, 3 ) : List( 2, 3 )).tail неверно, потому что левая сторона завершается, а правая - нет.

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

[10] Декларативное продолжение и категориальная двойственность, Филински , разделы 2.5.4 Сравнение CBV и CBN и 3.6.1 CBV и CBN в SCL.

[11] Декларативное продолжение и категориальная двойственность, Филински , разделы 2.2.1 Продукты и сопутствующие продукты, 2.2.2 Конечные и начальные объекты, 2.5.2 CBV с ленивыми продуктами и 2.5.3 CBN с активными сопутствующими продуктами.

person Shelby Moore III    schedule 02.12.2011
comment
Даже при декларативном программировании ограничений ограничения не изменяются, пока решатель находит решение. Это очевидно, потому что нет возможности указать время их изменения. Даже ограничения, указанные относительно все остальные ограничения указываются перед запуском решателя для поиска решения. Это аналогично декларативным формулам в электронной таблице. - person Shelby Moore III; 08.12.2011
comment
Аббревиатура не означает дать определение. Там, где я писал, что RT часто сокращенно называют «без побочных эффектов», это не означает, что определение RT - это отсутствие побочных эффектов, потому что у людей могут быть разные определения «эффектов». Если бы я вместо этого сказал, что RT часто сокращается как «xyz», бессмысленный символ не дает никакого определения RT. RT имеет точное определение, которое никогда не меняется, независимо от того, какой символ используется для его обозначения. - person Shelby Moore III; 08.12.2011
comment
Я не могу найти контрпример моему утверждению, что любой вид DP - это RT. Например, значение (то есть значение) терминов контекстно-зависимой грамматики не изменяется в разное время или в другом месте в грамматике. См. Мой комментарий по ограничению программирования выше. - person Shelby Moore III; 08.12.2011
comment
Приравнивание C в стиле ESP с RT в монаде состояния - это недействителен, поскольку каждая инструкция C может изменять глобальное состояние, тогда как внутри монады состояний каждый соответствующий оператор генерирует COPY состояния (измененного таким образом). Последнее - это RT, а первое - нет. Монадическая композиция всегда RT. DP == RT - единственное значение для DP, которое представляет собой непересекающийся набор атрибутов (математическое доказательство, что я прав, иначе DP не имеет смысла). - person Shelby Moore III; 08.12.2011
comment
При упоминании проверки завершения стоит упомянуть, что не все языки являются полными по Тьюрингу, и в них вы действительно можете гарантировать, что функции являются полными, например. Аппликативный Common Lisp 2. - person Barend Venter; 03.09.2012
comment
Некоторые люди заявляют, что SQL - это декларативный язык. Если это так, то разве SQL не имеет RT, поскольку он может изменять состояние (таблицы в базе данных)? Вызов одного и того же SQL-запроса в начале и в конце программы приведет к разным результатам. - person gsingh2011; 17.06.2014
comment
Вы говорите, что в декларативном программировании не может быть циклов. Но я могу представить чистую функцию, которая действительно содержит циклы, то есть он проходит через локальную коллекцию или коллекцию, переданную в функцию в качестве аргумента. Не будет ли точнее сказать, что декларативный язык не нуждается в циклах? - person Ronnie; 17.05.2015
comment
На истинном декларативном языке, разве вы не реализуете функции, а просто выбираете, какую функцию использовать, в каком порядке и с какими значениями? Под этим я подразумеваю, что разве реализация функции не является обязательной даже в чистом функциональном языке? - person Didier A.; 06.06.2015
comment
Хотел бы я понять это после первого предложения. Я читал руководство для DAX, в котором указывалось, что это «функциональный язык». Что это значит? Я не знаю, иди спроси свою попу. - person Nick.McDermaid; 04.05.2016
comment
Приведенное вами определение ссылочной прозрачности не получено и не соответствует определению в литературе; правильное определение см. в ответе Удая Редди. - person Maggyero; 15.07.2021

На самом деле для них нет однозначного, объективного определения. Вот как я их определил:

Обязательно. Основное внимание уделяется действиям, которые компьютер должен предпринять, а не тому, что он будет делать (например, C, C ++, Java).

Декларативный. Основное внимание уделяется тому, что компьютер должен делать, а не тому, как он должен это делать (например, SQL).

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

person Jason Baker    schedule 02.03.2009
comment
Рекурсия - не единственная особенность функциональных языков. У них также есть способы работы с функциями, отличными от просто компиляции, возможно, например, позволяя комбинировать функции во время выполнения для получения новой функции. - person David Thornley; 02.03.2009
comment
Имейте в виду пару вещей: 1) объяснение должно быть простым, а не всеобъемлющим; 2) как я уже сказал, существует несколько способов определения этих языков. Таким образом, ответ вполне может быть неправильным для вас и правильным для кого-то другого. - person Jason Baker; 02.03.2009
comment
Функциональное программирование не подмножество декларативных языков. Декларативное программирование требует неизменности хранимых значений, функциональное программирование не требует, если это не чистый FP. См. мой ответ. См. Также объяснение ячеек электронной таблицы. Правильные объективные определения не являются двусмысленными. Императивное программирование также сосредоточено на том, что должен делать компьютер. Единственное отличие состоит в том, что программирование обязательно должно иметь дело с изменяемыми сохраненными значениями. - person Shelby Moore III; 03.12.2011
comment
@ShelbyMooreIII - Я склонен согласиться с Эриком Мейером в этом вопросе. На самом деле не существует такой вещи, как нечистый функциональный язык. Насколько мне известно, Ocaml, F # и им подобные являются императивными языками с функциональными структурами данных. Но, как я сказал в своем ответе, я не верю, что на этот вопрос существует какой-либо объективный, однозначный ответ. Есть несколько способов определения вещей. - person Jason Baker; 09.12.2011
comment
Можно математически доказать, что он объединяет термины, когда ни одно из определений не является однозначным, потому что выбранные атрибуты не являются непересекающимся множеством. Если вы определяете FP как только чистый FP (т.е. RT), то он не отличается от DP, см. мой ответ. Непересекающиеся атрибуты FP включают тип функции первого класса, который может быть императивной функцией. Я обнаружил двусмысленность более фундаментальных терминов здесь и здесь. Предпочтение чистого FP ортогонально определению просто FP. - person Shelby Moore III; 09.12.2011
comment
Кто-то еще объясняет мою точку зрения. - person Shelby Moore III; 10.12.2011
comment
@ShelbyMooreIII - я предполагал, что ОП хотел, чтобы его ответ был на английском, а не на Math Nerd-ese. Если это было неверное предположение, приношу свои извинения. - person Jason Baker; 10.12.2011
comment
@JasonBaker Я стараюсь быть дружелюбным, помогая людям понять разницу между вещами. Иногда это может показаться снобистским, ботанистым или педантичным. Также извинения. Я уверен, что тоже буду учиться у вас. Программирование очень связано с логикой наборов. В основном это и есть набор текста. Этот навык станет гораздо более важным с появлением Scala и ему подобных. - person Shelby Moore III; 10.12.2011
comment
@JasonBaker Я отредактировал свой ответ и в разделе «Функциональное программирование» добавил сценарий, в котором мы могли бы утверждать, что FP всегда чистый и нечистый FP - это на самом деле процедурное программирование. Приносим извинения за то, что не включили эту интерпретацию ранее. - person Shelby Moore III; 12.12.2011
comment
Функция LINQ в языке C # функциональна по своей природе, когда сам язык является императивным. В C # также есть атрибуты, например [Serializable], с помощью которых вы можете украсить свои классы и методы. Эти атрибуты также функциональны по своей природе. - person RBT; 08.12.2016
comment
FP - это подмножество императивного программирования. Всего 2 класса: императивный и декларативный. - person RandomB; 11.08.2017

императивный и декларативный описывают два противоположных стиля программирования. императивом является традиционный подход «пошаговый рецепт», в то время как декларативным является больше «это то, что я хочу, теперь вы решаете, как это сделать».

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

с другой стороны, императивный подход дает вам более низкий уровень контроля - это «подход микроменеджера» к программированию. и это может позволить программисту использовать знания о проблеме, чтобы дать более эффективный ответ. поэтому нет ничего необычного в том, что некоторые части программы пишутся в более декларативном стиле, а части, критичные к скорости, становятся более императивными.

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

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

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

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

резюмируя, то:

  • императивный и декларативный - два противоположных стиля программирования (одни и те же имена используются для языков программирования, которые поощряют эти стили)

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

поэтому «функциональное программирование» часто называют «декларативным».

person andrew cooke    schedule 05.09.2011
comment
Лучшее объяснение на данный момент. Кажется, что функциональный и ООП ортогональны императивному и декларативному. - person Didier A.; 06.06.2015
comment
Вы бы сказали, что логическое программирование декларативно? Или он сам ортогонален? - person Didier A.; 06.06.2015

В двух словах:

Императивный язык определяет последовательность инструкций, которые компьютер выполняет последовательно (сделайте то, затем сделайте то).

Декларативный язык объявляет набор правил о том, какие выходные данные должны быть результатом каких входов (например, если у вас есть A, то результатом будет B). Двигатель будет применять эти правила к входам и выдавать выходные данные.

Функциональный язык объявляет набор математических / логических функций, которые определяют, как ввод преобразуется в вывод. например. f (y) = y * y. это тип декларативного языка.

person mdja    schedule 02.03.2009
comment
Функциональное программирование не разновидности декларативного языка. Декларативное программирование требует неизменности хранимых значений, в отличие от нечистого функционального программирования. См. мой ответ. См. Также объяснение ячеек электронной таблицы. Единственная причина, по которой императивная логика (также известная как инструкции) выполняется последовательно, заключается в том, что из-за наличия изменяемых сохраненных значений результат зависит от порядка оценки. Используя ваш словарь, инструкция может (а правило не может) работать с изменяемыми значениями. - person Shelby Moore III; 03.12.2011

Настоятельно необходимо: как достичь нашей цели

   Take the next customer from a list.
   If the customer lives in Spain, show their details.
   If there are more customers in the list, go to the beginning

Декларативно: чего мы хотим достичь.

   Show customer details of every customer living in Spain
person Arturo Herrero    schedule 23.10.2011
comment
Вы описываете функциональное программирование и не-FP, а не декларативное и императивное программирование. Функциональное программирование ортогонально полярности между императивным и декларативным программированием. Декларативное программирование требует неизменности хранимых значений, в отличие от нечистого функционального программирования. См. мой ответ. - person Shelby Moore III; 03.12.2011

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

Декларативное программирование означает любой стиль программирования, в котором ваша программа является описанием проблемы или решения, но не указывает явно, как будет выполняться работа.

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

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

Перезапись терминов (например, CASL) - это еще одна форма декларативного программирования. Он включает в себя символическое преобразование алгебраических терминов. Это полностью отличается от логического программирования и функционального программирования.

person Dafydd Rees    schedule 03.05.2011
comment
Функциональное программирование - это не форма декларативного программирования. Декларативное программирование требует неизменности хранимых значений, в отличие от нечистого функционального программирования. См. мой ответ. См. Также объяснение ячеек электронной таблицы. Термин «работа» в описании того, как выполнять работу, не определен. Единственная причина, по которой императивная логика (также известная как инструкции) выполняется последовательно, заключается в том, что из-за наличия изменяемых сохраненных значений результат зависит от порядка оценки. - person Shelby Moore III; 03.12.2011
comment
Примите как прочитанное, что я говорил о чисто функциональном программировании. Эти парадигмы могут пересекаться, и я не хочу увязнуть в сравнении гибридных языков. Теоретически, по крайней мере, функциональное программирование связано с функциями, а не с описанием того, как компьютер будет выполнять каждое вычисление, поэтому я считаю его декларативным. - person Dafydd Rees; 11.12.2011
comment
Я отредактировал свой ответ и в разделе «Функциональное программирование» добавил сценарий, в котором мы могли бы утверждать, что FP всегда чист, а нечистый FP - это на самом деле процедурное программирование. Приносим извинения за то, что не включили эту интерпретацию ранее. - person Shelby Moore III; 12.12.2011

императив - выражения описывают последовательность действий, которые необходимо выполнить (ассоциативно)

декларативное - выражения - это объявления, которые способствуют поведению программы (ассоциативное, коммутативное, идемпотентное, монотонное).

функциональный - выражения имеют значение только как эффект; семантика поддерживает эквациональные рассуждения

person dmbarbour    schedule 07.08.2012
comment
Декларативные выражения влияют на предполагаемое поведение программы императив может способствовать преднамеренному или непреднамеренному. Декларативность не обязательно должна быть коммутативной и идемпотентной, если это намеренная семантика. Мне нравится ваша лаконичная суть функционала, поэтому я положительно оценила его. - person Shelby Moore III; 28.02.2013

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

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

Процитированное объяснение определения обсуждает роль, которую чистое функциональное программирование играет в декларативном программировании.

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

Декларативное и императивное

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

Было бы слишком упрощенно, технически неточно и часто двусмысленно определять декларативное как «что делать» и императивное как «как делать. Неоднозначным случаем является то, что «что» является «как» в программе, которая выводит программу - компилятор.

Очевидно, неограниченная рекурсия, которая делает язык Тьюринга полным, также аналогичным образом присутствует в семантика - не только в синтаксической структуре оценки (также известной как операционная семантика). Логически это пример, аналогичный теореме Гёделя: «любая полная система аксиом также несовместима». Вдумайтесь в противоречивую странность этой цитаты! Это также пример, демонстрирующий, что выражение семантики не имеет доказуемой границы, поэтому мы не можем доказать 2, что программа (и аналогично ее семантика) останавливает, также известную как теорема об остановке.

Теоремы о неполноте проистекают из фундаментальной природы нашей Вселенной, которая, как сказано во втором законе термодинамики, состоит в том, что «энтропия (также известная как количество независимых возможностей) всегда стремится к максимуму ». Кодирование и дизайн программы никогда не заканчиваются - она ​​живая! - потому что она пытается удовлетворить потребности реального мира, а семантика реального мира всегда меняется и стремится к большему количеству возможностей. Люди никогда не перестают открывать для себя что-то новое (включая ошибки в программах ;-).

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

Определение:


В декларативном свойстве может существовать только один возможный набор операторов, который может выражать каждую конкретную модульную семантику.

Императивное свойство 3 является двойным, при котором семантика несовместима по составу и / или могут быть выражены вариациями наборов утверждений.


Это определение декларативного является явно локальным в семантической области, что означает, что оно требует, чтобы модульная семантика сохраняла свое согласованное значение независимо от того, где и как она создается и используется в глобальной области. Таким образом, каждая декларативная модульная семантика должна быть изначально ортогональна всем возможным другим, а не невозможным (из-за теорем о неполноте) глобальным алгоритмом или моделью для проверки согласованности, что также является точкой « Больше не всегда лучше »Роберта Харпера, профессора компьютерных наук в Университете Карнеги-Меллона, одного из разработчиков Standard ML.

Примеры этой модульной декларативной семантики включают функторы теории категорий, например. Applicative, номинальная типизация, пространства имен, именованные поля и w.r.t. до операционного уровня семантики, затем чисто функционального программирования.

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

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

Язык гипертекстовой разметки, также известный как HTML, язык для статических веб-страниц, является примером очень (но не идеального) 3) декларативный язык, который (по крайней мере, до HTML 5) не имел возможности выражать динамическое поведение. HTML, пожалуй, самый простой язык для изучения. Для динамического поведения императивный язык сценариев, такой как JavaScript, обычно сочетался с HTML. HTML без JavaScript соответствует декларативному определению, потому что каждый номинальный тип (то есть теги) сохраняет свое согласованное значение при композиции в рамках правил синтаксиса.

Конкурирующим определением декларативного является определение коммутативного и idempotent семантических утверждений, то есть эти утверждения можно переупорядочивать и дублировать без изменения значения. Например, операторы, присваивающие значения именованным полям, могут быть переупорядочены и дублированы без изменения смысла программы, если эти имена являются модульными w.r.t. на любой подразумеваемый заказ. Иногда имена подразумевают порядок, например идентификаторы ячеек включают их столбец и позицию строки - перемещение итога в электронной таблице меняет его значение. В противном случае эти свойства неявно требуют глобальной согласованности семантики. Как правило, невозможно спроектировать семантику операторов, чтобы они оставались согласованными при случайном порядке или дублировании, потому что порядок и дублирование являются неотъемлемой частью семантики. Например, утверждения «Foo существует» (или конструкция) и «Foo не существует» (и разрушение). Если рассматривать случайную несогласованность, присущую предполагаемой семантике, то это определение принимается как достаточно общее для декларативного свойства. По сути, это определение бессмысленно как обобщенное определение, потому что оно пытается сделать согласованность ортогональной семантике, то есть игнорировать тот факт, что универсум семантики динамически неограничен и не может быть зафиксирован в глобальной согласованности парадигма.

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

C, Java, C ++, C #, PHP и JavaScript не особо декларативны. Синтаксис Copute и синтаксис Python более декларативно связаны с предполагаемыми результатами, т. Е. Согласованной синтаксической семантикой, исключающей посторонние так что можно легко понять код после того, как они его забыли. Copute и Haskell обеспечивают детерминизм операционной семантики и поощряют «не повторяться» (DRY), потому что они допускают только чисто функциональную парадигму.


2 Даже если мы можем доказать семантику программы, например в языке Coq это ограничено семантикой, которая выражена в типизации, и типизация никогда не может охватить всю семантику программы - даже для языков, не являющихся полными по Тьюрингу, например с помощью HTML + CSS можно выражать противоречивые комбинации, которые, таким образом, имеют неопределенную семантику.

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


Изменить: я разместил следующий комментарий к блогу Роберта Харпера:

в функциональном программировании ... диапазон изменения переменной - это тип

В зависимости от того, как отличить функциональное программирование от императивного, ваш «назначаемый» в императивной программе также может иметь тип, ограничивающий его изменчивость.

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

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

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

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

Таким образом, я пришел к выводу, что декларативными могут быть только полные по Тьюрингу языки.

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

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

Лези Лэмпорт написала сказку о том, как Евклид мог работали над теоремами Гёделя о неполноте, примененными к математическим доказательствам в контексте языка программирования, для соответствия между типами и логикой (соответствие Карри-Ховарда и т. д.).

person Shelby Moore III    schedule 13.03.2013
comment
Роберт Харпер, кажется, согласен со мной по поводу бессмысленность большинства декларативных определений, но я не думаю, что он видел мое выше. Он действительно приближается к моему определению, где обсуждает денотационную семантику, но не доходит до моего определения. Модель (денотационная семантика) является более высокоуровневой. - person Shelby Moore III; 16.09.2013
comment
Как вы классифицируете SQL? - person Maggyero; 15.07.2021

Императивное программирование: говорите «машине», как что-то делать, и в результате произойдет то, что вы хотите.

Декларативное программирование: сообщая «машине», что вы хотите, и позволяя компьютеру выяснить, как это сделать.

Пример императивного

function makeWidget(options) {
    const element = document.createElement('div');
    element.style.backgroundColor = options.bgColor;
    element.style.width = options.width;
    element.style.height = options.height;
    element.textContent = options.txt;

    return element;
}

Пример декларативного

function makeWidget(type, txt) {
    return new Element(type, txt);
}

Примечание: разница не в краткости, сложности или абстракции. Как уже говорилось, разница в том, как и что.

person yondoo    schedule 19.12.2013
comment
хороший, но лучше, если вы приведете хотя бы один пример для обоих! - person Pardeep Jain; 06.02.2016

В наши дни новый фокус: нам нужны старые классификации?

Императивные / декларативные / функциональные аспекты были хороши в прошлом для классификации общих языков, но в настоящее время у всех «больших языков» (таких как Java, Python, Javascript и т. Д.) Есть некоторые опции (обычно frameworks), чтобы выразить "другой фокус", чем его основной (обычно императив), и чтобы выразить параллель процессы, декларативные функции, лямбды и т. д.

Итак, хороший вариант этого вопроса: «Какой аспект сегодня хорош для классификации фреймворков?» ... Важный аспект - это то, что мы можем обозначить как «стиль программирования». ..

Сосредоточьтесь на слиянии данных с алгоритмом

Хороший пример для объяснения. Как вы можете прочитать о jQuery в Википедии,

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

Итак, jQuery - лучший (популярный) пример фокусировки на "новом стиле программирования", который не только ориентирован на объект, - это "Fusing алгоритмы и структуры данных". jQuery в некоторой степени реагирует на электронные таблицы, но не «ориентирован на ячейки», он «ориентирован на DOM-узел» ... Сравнение основных стилей в этом контексте:

  1. Никакого слияния: во всех "больших языках", в любом функциональном / декларативном / императивном выражении обычным является "отсутствие слияния" данных и алгоритма, за исключением некоторой объектной ориентации, т. е. слияние с точки зрения строгой алгебрической структуры.

  2. Некоторое слияние: все классические стратегии слияния в настоящее время имеют некоторую структуру, использующую его как парадигму ... поток данных, событийно-ориентированное программирование (или старый домен определенные языки как awk и XSLT) ... Как и программирование с использованием современных электронных таблиц, они также являются примерами реактивное программирование.

  3. Big fusion: это "стиль jQuery" ... jQuery - это язык для конкретной предметной области, ориентированный на "объединение алгоритмов и DOM-структуры данных".
    PS: другие "языки запросов", такие как XQuery, SQL (с PL в качестве обязательного параметра выражения), также являются примерами слияния алгоритмов данных, но они являются островами, без слияния с другими системные модули ... Spring при использовании find()-вариантов и спецификации clauses - еще один хороший пример слияния.

person Peter Krauss    schedule 01.07.2013

Декларативное программирование - это программирование, выражающее некоторую вневременную логику между входом и выходом, например, в псевдокоде следующий пример будет декларативным:

def factorial(n):
  if n < 2:
    return 1
  else:
    return factorial(n-1)

output = factorial(argvec[0])

Мы просто определяем здесь отношение, называемое факториалом, и определили отношение между выходом и входом как это отношение. Здесь должно быть очевидно, что любой структурированный язык в некоторой степени допускает декларативное программирование. Центральная идея декларативного программирования - неизменяемые данные: если вы присваиваете переменную, вы делаете это только один раз и никогда больше. Другие, более строгие определения влекут за собой отсутствие побочных эффектов вообще, эти языки иногда называют «чисто декларативными».

Тот же результат в императивном стиле будет:

a = 1
b = argvec[0]
while(b < 2):
  a * b--

output = a

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

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

К чисто декларативным языкам относятся Haskell и Pure Prolog. Скользящая шкала от одного к другому будет: Pure Prolog, Haskell, OCaml, Scheme / Lisp, Python, Javascript, C--, Perl, PHP, C ++, Pascall, C, Fortran, Assembly.

person Zorf    schedule 08.06.2010
comment
Вы не определили функциональное программирование. Вы неправильно подразумевали, некоторые «чисто» декларативные языки, что декларативное программирование может быть нечистым. Декларативное программирование требует неизменности хранимых значений, а императивное программирование - нет. См. мой ответ. Неизменяемость - это вечное качество - убедитесь, что ваш декларативный factorial не изменяет никакого значения. - person Shelby Moore III; 03.12.2011

Здесь есть несколько хороших ответов относительно отмеченных "типов".

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

  • Язык, специфичный для домена или Программирование DSL: создание нового языка для решения возникшей проблемы.
  • Мета-программирование: когда ваша программа пишет другие программы.
  • Эволюционное программирование: вы создаете систему, которая постоянно совершенствуется или генерирует все более совершенные поколения подпрограмм.
person msmithgu    schedule 09.04.2013

Я считаю, что ваша таксономия неверна. Есть два противоположных типа: императивный и декларативный. Функциональный - это всего лишь подтип декларативного. Кстати, википедия утверждает тот же факт.

person Rorick    schedule 02.03.2009
comment
+1: Ага, парадигмы - яблоки и апельсины. - person Nikhil Chelliah; 02.03.2009
comment
FP - это не просто декларативный подтип. FP ортогонален полярности императивного и DP. DP требует неизменности сохраненных значений, а нечистые FP - нет. Википедия объединяет чистый FP с FP с помощью абсурдное утверждение, что следующие концепции обычно чужды императивному программированию: функции первого класса, рекурсия, порядок оценки и статическая типизация. Затем Википедия допускает нечистое функциональное программирование на нефункциональных языках. - person Shelby Moore III; 03.12.2011
comment
Википедия ошибается в этом вопросе. Многие популярные функциональные языки позволяют программировать в декларативном стиле, если вы хотите, но не являются декларативными языками. Но то же самое можно сказать и о C, где вы все еще можете программировать в функциональном стиле, если захотите, используя void * s. - person Plynx; 03.10.2012
comment
Возможно, мне следовало быть более ясным по этому поводу, но, с другой стороны, я бы не стал путать тему стартера с не совсем актуальными (имо) деталями. Я вижу, что функциональные языки обычно используются декларативно. Вы можете попробовать писать декларативно и / или функционально на ASM или C, или вы, вероятно, можете написать императивную программу на Lisp, но я сомневаюсь, что это было бы очень полезно или информативно для автора вопроса. Так что, по сути, я все же считаю свой ответ правильным, даже если бы его можно было сформулировать иначе. - person Rorick; 05.10.2012

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

person jchadhowell    schedule 20.08.2009
comment
Смотрите мои комментарии под другими ответами. ФП не всегда декларативна. Что и как - неправильная таксономия для IP и DP, поскольку и DP, и IP имеют логику, которая включает в себя что и как. - person Shelby Moore III; 03.12.2011