Функциональное, декларативное и императивное программирование
Что означают термины функциональное, декларативное и императивное программирование?
Ответы
Ответ 1
Во время написания этого ответа верхние голосовые ответы на этой странице неточны и запутаны в декларативном и императивном определении, включая ответ, который цитирует Википедию. Некоторые ответы объединяют термины по-разному.
Обратитесь также к моим объяснениям о том, почему программирование таблиц является декларативным, независимо от того, что формулы мутируют ячейки.
Кроме того, в нескольких ответах утверждается, что функциональное программирование должно быть подмножеством декларативных. В этом случае это зависит от того, будем ли мы дифференцировать "функцию" от "процедуры". Давайте сначала обработаем императив против декларативного.
Определение декларативного выражения
Атрибут только, который может дифференцировать декларативное выражение из императивного выражения, - это ссылочная прозрачность (RT) его подвыражений. Все остальные атрибуты либо разделяются между двумя типами выражений, либо производятся от RT.
100% декларативный язык (т.е. тот, в котором все возможные выражения являются RT) не позволяет (среди других требований RT) допускать мутацию сохраненных значений, например. HTML и большую часть Haskell.
Определение выражения RT
RT часто называют "без побочных эффектов". Термин эффекты не имеет точного определения, поэтому некоторые люди не согласны с тем, что "никаких побочных эффектов" не отличается от RT. RT имеет точное определение.
Поскольку каждое подвыражение является концептуально вызовом функции, RT требует, чтобы реализация функции (т.е. выражение (выражения) внутри вызываемой функции) не имела доступа к изменяемому состоянию, которое является внешним по отношению к функции (доступ к изменяемое локальное состояние). Проще говоря, функция (реализация) должна быть чистой.
Определение чистой функции
Чистая функция часто называется "без побочных эффектов". Термин эффекты не имеет точного определения, поэтому некоторые люди не согласны.
Чистые функции имеют следующие атрибуты.
- единственным наблюдаемым выходом является возвращаемое значение.
- единственная выходная зависимость - это аргументы.
Аргументы
- полностью определены до генерирования любого результата.
Помните, что RT применяется к выражениям (включая вызовы функций), и чистота применяется к (реализациям) функций.
Неясным примером нечистых функций, которые делают выражения RT, является concurrency, но это связано с тем, что чистота разбита на уровне абстракции прерывания. Вам действительно не нужно это знать. Чтобы сделать выражения RT, вы вызываете чистые функции.
Производные атрибуты RT
Любой другой атрибут, указанный для декларативного программирования, например. цитата из 1999, используемая Wikipedia, либо происходит от RT, либо разделяется с императивным программированием. Таким образом, доказательство правильности моего точного определения.
Примечание, неизменность внешних значений является подмножеством требований к RT.
-
В декларативных языках нет структур управления циклом, например. for
и while
, потому что из-за неизменяемости, условие цикла никогда не изменится.
-
Декларативные языки не выражают поток управления, отличный от вложенного функционального порядка (так называемые логические зависимости), потому что из-за неизменности другие варианты оценки не меняют результат (см. ниже).
-
Декларативные языки выражают логические "шаги" (т.е. порядок вызова вложенных функций RT), но не является ли каждый вызов функции более строгим семантиком (то есть "что делать" ) не является требованием декларативного программирования. Отличие от императива состоит в том, что из-за неизменности (т.е. В целом RT), эти "шаги" не могут зависеть от изменчивого состояния, а скорее от реляционного порядка выраженной логики (т.е. Порядка вложенности вызовы функций, aka подвыражения).
Например, HTML-абзац <p>
не может отображаться до тех пор, пока не будут оценены подвыражения (т.е. теги) в абзаце. Нет измененного состояния, только зависимость от заказа из-за логической связи иерархии тегов (вложенность подвыражений, которые аналогично вложенные вызовы функций).
-
Таким образом, существует производный атрибут неизменяемости (в более общем смысле RT), что декларативные выражения выражают только логические отношения составляющих частей (т.е. аргументов функции подвыражения), а не изменяемые отношения состояний.
Порядок оценки
Выбор порядка оценки подвыражений может дать только переменный результат, если любой из вызовов функций не является RT (т.е. функция не является чистой), например. к некоторому изменяемому состоянию, внешнему по отношению к функции, доступна функция.
Например, с учетом некоторых вложенных выражений, например. f( g(a, b), h(c, d) )
, нетерпеливая и ленивая оценка аргументов функции даст те же результаты, если функции f
, g
и h
являются чистыми.
Если функции f
, g
и h
не являются чистыми, то выбор порядка оценки может дать другой результат.
Примечание. Вложенные выражения представляют собой концептуально вложенные функции, поскольку операторы выражения - это просто вызовы функций, маскирующиеся как унарный префикс, унарный постфикс или двоичная инфиксная нотация.
Тангенциально, если все идентификаторы, например. a
, b
, c
, d
, неизменяемы повсюду, невозможно получить доступ к внешнему внешнему виду программы (т.е. I/O), и нет обрыва слоя абстракции, тогда функции всегда чисты.
Кстати, у Haskell есть другой синтаксис, f (g a b) (h c d)
.
Сведения о порядке оценки
Функция представляет собой переход состояния (не изменяемое сохраненное значение) от входа к выходу. Для RT-составов вызовов чистых функций порядок выполнения этих состояний не зависит. Переход состояния каждого вызова функции не зависит от других, из-за отсутствия побочных эффектов и принципа, что функция RT может быть заменена кеш-значением. Чтобы исправить распространенное заблуждение, чистая монадическая композиция всегда декларативная и RT, несмотря на то, что Haskell IO
monad возможно, нечистый и, следовательно, состояние World
, внешнее по отношению к программе (но в смысле нижеследующего предостережения, побочные эффекты изолированы).
Ожидаемая оценка означает, что аргументы функций оцениваются до вызова функции, а ленивая оценка означает, что аргументы не оцениваются до (и если) они доступны в пределах функции.
Определение: параметры функции объявляются на сайте определения функции, а аргументы функции предоставляются на сайте вызова функции. Знайте разницу между параметром и аргументом.
Концептуально все выражения являются (составными) вызовами функций, например. константы - это функции без входов, унарные операторы - это функции с одним входом, двоичные инфиксные операторы - это функции с двумя входами, конструкторы - это функции, и даже управляющие операторы (например, if
, for
, while
) могут быть смоделированы с функциями, порядок, чтобы эти функции аргументов (не путать с порядком вызова вложенных функций) оценивались, не объявляется синтаксисом, например. f( g() )
может с нетерпением оценить g
, а затем f
на результат g
или он мог бы оценить f
и лениво оценивать g
, когда его результат необходим в f
.
Caveat, no Turing complete (то есть, который допускает неограниченную рекурсию), является совершенно декларативным, например. ленивая оценка вводит память и неопределенность времени. Но эти побочные эффекты, связанные с выбором порядка оценки, ограничены потреблением памяти, временем выполнения, задержкой, отсутствием прерывания и внешним гистерезисом, таким образом, внешней синхронизацией.
Функциональное программирование
Поскольку декларативное программирование не может иметь циклов, то единственным способом повторения является функциональная рекурсия. Именно в этом смысле функциональное программирование связано с декларативным программированием.
Но функциональное программирование не ограничивается декларативным программированием. Функциональная композиция может быть контрастирована с подтипированием, особенно в отношении Проблема выражения, где расширение может быть достигнуто посредством либо добавление подтипов, либо функциональная декомпозиция. Расширение может быть комбинацией обеих методологий.
Функциональное программирование обычно делает функцию первоклассным объектом, то есть тип функции может отображаться в грамматике везде, где может быть любой другой тип. Результатом является то, что функции могут вводить и работать с функциями, обеспечивая тем самым разделение проблем, подчеркивая состав функции, т.е. Разделяя зависимости между подвычислениями детерминированного вычисления.
Например, вместо написания отдельной функции (и использование рекурсии вместо циклов, если функция также должна быть декларативной) для каждого из бесконечное количество возможных специализированных действий, которые могут быть применены к каждому элементу коллекции, функциональное программирование использует многократно используемые итерационные функции, например map
, fold
, filter
. Эти итерационные функции вводят специализированную функцию действия первого класса. Эти итерационные функции выполняют итерацию коллекции и вызывают функцию специализированного действия ввода для каждого элемента. Эти функции действия более кратки, потому что им больше не нужно содержать операторов цикла для итерации коллекции.
Однако обратите внимание, что если функция не чистая, то это действительно процедура. Возможно, мы можем утверждать, что функциональное программирование, использующее нечистые функции, действительно является процедурным программированием. Таким образом, если мы согласны с тем, что декларативные выражения являются RT, то можно сказать, что процедурное программирование не является декларативным программированием, и поэтому мы можем утверждать, что функциональное программирование всегда RT и должно быть подмножеством декларативного программирования.
Parallelism
Эта функциональная композиция с первоклассными функциями может выразить глубину в parallelism, разделив независимую функцию.
Принцип Брентса: вычисление с работой w и глубиной d может быть реализованный в p-процессоре PRAM за время O (max (w/p, d)).
Оба concurrency и parallelism также требуют декларативного программирования, т.е. неизменяемости и RT.
Так где же это опасное предположение, что parallelism == Concurrencyродом из? Это естественное следствие языков с побочными эффектами: когда ваш язык имеет побочные эффекты во всем мире, то в любое время, когда вы пытаетесь делать больше, чем когда-либо, в то время недетерминизм, вызванный чередованием эффектов от каждого операция. Таким образом, на побочных эффектах, единственный способ получить parallelism - concurrency; поэтому неудивительно, что мы часто видят два сложенных.
Порядок оценки FP
Обратите внимание, что порядок оценки также влияет на побочные эффекты завершения и производительности функциональной композиции.
Ожидающие (CBV) и ленивые (CBN) - это категорические дуэли [10], потому что они изменили порядок оценки, т.е. вне зависимости от того, внутренние функции соответственно оцениваются первыми. Представьте себе перевернутое дерево, а затем нетерпеливые оценки от ветки дерева функций подсказывают иерархию ветвей в соединительной линии верхнего уровня; тогда как, ленивый, оценивает от ствола до кончиков ветки. У нетерпения нет конъюнктивных продуктов ( "и", a/k/a категориальных "продуктов" ) и ленивый не имеет дизъюнктивных копроизведений ( "или", a/k/a категориальных "сумм" ) [11].
Производительность
-
Страстно
Как и в случае без прерывания, нетерпеливый слишком нетерпелив с конъюнктивной функциональной композицией, т.е. структура управления композицией делает ненужную работу, которая не выполняется с ленивым. Для пример, нетерпеливо и излишне отображает весь список в booleans, когда он составлен с помощью складки, которая заканчивается на первом истинном элементе.
Эта ненужная работа является причиной заявленного "до" дополнительного log n factor в последовательной временной сложности нетерпеливых против ленивых, как с чистыми функциями. Решением является использование функторов (например, списков) с ленивыми конструкторами (т.е. Нетерпеливыми с необязательными ленивыми продуктами), потому что с нетерпением нетерпеливость возникает из внутренней функции. Это потому, что продукты являются конструктивными типами, т.е. Индуктивными типами с начальной алгеброй на начальной фиксированной точке [11]
-
Ленивый
Как и без прерывания, ленивый слишком ленив с дизъюнктивной функциональной композицией, то есть коиндуктивная финальность может произойти позже, чем необходимо, что приводит к как ненужной работе, так и недетерминированности позднего времени, что не имеет места с нетерпением [10] [11]. Примерами конечных результатов являются состояния, время, исключение и исключение времени выполнения. Это обязательные побочные эффекты, но даже на чистом декларативном языке (например, Haskell) существует состояние в императивной монаде IO (обратите внимание: не все монады являются обязательными!), Скрытые в распределении пространства, а время - состояние относительно императива реальный мир. Использование ленивых даже с необязательными энергичными копродуктами утечки "лени" во внутренние сопутствующие товары, потому что с ленивой неправильностью лень возникает из внешней функции (см. Пример в раздел Non-term, где == - внешняя двоичная операторная функция). Это связано с тем, что копроизведения ограничены конечностью, т.е. Коиндуктивными типами с конечной алгеброй на конечном объекте [11].
Lazy вызывает индетерминизм в дизайне и отладке функций для латентности и пространства, отладка которых, вероятно, выходит за рамки возможностей большинства программистов, из-за диссонанс между объявленной иерархией функций и порядковой оценкой времени выполнения. Ленивые чистые функции, оцененные с нетерпением, могут потенциально представить ранее невидимое без прерывания во время выполнения. Напротив, нетерпеливые чистые функции, оцененные с ленивым, потенциально могут представить ранее невидимое индексирование пространства и латентности во время выполнения.
незавершение
Во время компиляции из-за проблемы с остановкой и взаимной рекурсии на полном языке Turing функции обычно не могут быть завершены.
-
Страстно
С нетерпением, но не ленив, для соединения Head
"и" Tail
, если либо Head
, либо Tail
не заканчивается, то соответственно либо List( Head(), Tail() ).tail == Tail()
, либо List( Head(), Tail() ).head == Head()
неверно потому что левая сторона не делает, а правая сторона заканчивается.
В то время как с ленивыми обеими сторонами заканчиваются. Таким образом, нетерпеливый слишком нетерпим к конъюнктивным продуктам и не завершает работу (включая исключения времени выполнения) в тех случаях, когда это необязательно.
-
Ленивый
С ленивым, но не нетерпеливым, для дизъюнкции 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 с нетерпеливыми копроизведениями.
Ответ 2
На самом деле нет никакого недвусмысленного, объективного определения для них. Вот как бы я определил их:
Императив. Основное внимание уделяется тем, какие шаги должен предпринять компьютер, а не то, что компьютер будет делать (например, C, С++, Java).
Декларативный. Основное внимание уделяется тому, что должен делать компьютер, а не как ему это делать (например, SQL).
Функциональный - подмножество декларативных языков, сильно фокусирующихся на рекурсии
Ответ 3
императив и декларативный описывают два противоположных стиля программирования. императив - это традиционный подход "пошаговый рецепт", в то время как декларативный - это "это то, что я хочу", теперь вы определяете, как это сделать ".
эти два подхода встречаются во время программирования - даже с одним и тем же языком и с той же программой. как правило, декларативный подход считается предпочтительным, поскольку он освобождает программиста от необходимости указывать так много деталей, а также имеет меньше шансов на ошибки (если вы описываете результат, который вы хотите, и какой-либо проверенный автоматический процесс может работать в обратном направлении от этого до определите шаги, тогда вы можете надеяться, что вещи более надежны, чем указать каждый шаг вручную).
с другой стороны, императивный подход дает вам более низкий уровень контроля - это "подход микроменеджера" к программированию. и это может позволить программисту использовать знания о проблеме, чтобы дать более эффективный ответ. поэтому для некоторых частей программы нет ничего необычного в более декларативном стиле, но для критически важных деталей необходимо быть более императивным.
как вы можете себе представить, язык, который вы используете для написания программы, влияет на то, насколько декларативным вы можете быть - язык, который имеет встроенные "умники" для разработки того, что делать, с учетом описания результата, позволит гораздо более декларативный подход, чем тот, где программисту необходимо сначала добавить этот вид интеллекта с императивным кодом, прежде чем он сможет создать более декларативный слой сверху. поэтому, например, язык, подобный прологу, считается очень декларативным, поскольку он имеет встроенный процесс, который ищет ответы.
вы заметите, что я не упомянул о функциональном программировании. что, поскольку это термин, смысл которого не сразу связан с двумя другими. в самом простом, функциональном программировании означает, что вы используете функции. в частности, что вы используете язык, который поддерживает функции как "значения первого класса" - это означает, что вы не только можете писать функции, но и писать функции, которые записывают функции (которые записывают функции, которые...), и передавать функции функции. Короче говоря, эти функции являются такими же гибкими и обычными, как и строки и числа.
может показаться странным, то, что функциональные, императивные и декларативные часто упоминаются вместе. причина этого - следствие того, что понятие функционального программирования "до крайности". функция, в этом чистом смысле, является чем-то вроде математики - своего рода "черным ящиком", который принимает некоторый вклад и всегда дает тот же результат. и такое поведение не требует хранения переменных переменных. поэтому, если вы разрабатываете язык программирования, целью которого является реализация очень чистой математически влиятельной идеи функционального программирования, вы в конечном итоге отвергаете идею ценностей, которые могут меняться (в определенном, ограниченном техническом смысле).
и если вы это сделаете - если вы ограничите, как переменные могут измениться, то почти случайно вы в конечном итоге вынуждаете программиста писать программы, более декларативные, потому что большая часть императивного программирования описывает изменение переменных, а вы больше не может этого делать! поэтому оказывается, что функциональное программирование - в частности, программирование на функциональном языке - имеет тенденцию давать более декларативный код.
чтобы суммировать, затем:
-
императивные и декларативные два противоположных стиля программирования (те же имена используются для языков программирования, которые поощряют эти стили)
-
функциональное программирование - это стиль программирования, где функции становятся очень важными, и, как следствие, изменение ценностей становится менее важным. ограниченная способность указывать изменения в значениях создает более декларативный стиль.
поэтому "функциональное программирование" часто описывается как "декларативное".
Ответ 4
В двух словах:
обязательный язык отображает ряд инструкций, которые компьютер выполняет последовательно (сделайте это, затем сделайте это).
A декларативный язык объявляет набор правил о том, какие выходные результаты должны быть получены из входов (например, если у вас есть A, то результатом является B). Двигатель будет применять эти правила к входам и выдавать результат.
A функциональный язык объявляет набор математических/логических функций, которые определяют, как ввод преобразуется в вывод. например. f (y) = y * y. это тип декларативного языка.
Ответ 5
Императив: как для достижения нашей цели
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
Ответ 6
Императивное программирование означает любой стиль программирования, в котором ваша программа структурирована из инструкций , описывающих, как будут выполняться операции, выполняемые компьютером.
Декларативное программирование означает любой стиль программирования, в котором ваша программа является описанием проблемы или решения, но не указывает, как будет работать работа.
Функциональное программирование - это программирование путем оценки функций и функций функций... Поскольку (строго определенное) функциональное программирование означает программирование, определяя свободные побочные эффекты, математические функции, поэтому он является формой декларативное программирование, но это не единственный вид декларативного программирования.
Логическое программирование (например, в Prolog) - это еще одна форма декларативного программирования. Это включает в себя вычисление путем принятия решения о том, является ли логическое утверждение истинным (или оно может быть выполнено). Программа, как правило, представляет собой ряд фактов и правил, то есть описание, а не последовательность инструкций.
Переписывание терминов (например, CASL) - это еще одна форма декларативного программирования. Он включает символическое преобразование алгебраических членов. Он полностью отличается от логического программирования и функционального программирования.
Ответ 7
императив - выражения описывают последовательность действий для выполнения (ассоциативный)
декларативный - выражения - это объявления, которые способствуют поведению программы (ассоциативной, коммутативной, идемпотентной, монотонной)
функциональный - выражения имеют значение только как эффект; семантика поддерживает экваториальное мышление
Ответ 8
Поскольку я написал свой предыдущий ответ, я сформулировал новое определение декларативного свойства, которое приведено ниже. Я также определил императивное программирование как двойное свойство.
Это определение превосходит то, которое я представил в моем предыдущем ответе, потому что оно кратким и более общим. Но это может быть труднее заглянуть, потому что имплементация теорем о неполноте, применимых к программированию и жизни в целом, людям трудно обдумать.
В цитируемом объяснении определения обсуждается роль, которую играет чисто функциональное программирование в декларативном программировании.
Все экзотические типы программирования вписываются в следующую таксономию декларативного и императивного, поскольку следующее определение утверждает, что они являются двойственными.
Декларативный и императивный
Декларативное свойство является странным, тупым и трудным для захвата в технически точном определении, которое остается общим, а не двусмысленным, потому что это наивное представление о том, что мы можем объявить значение (ака семантики) программы без возникновения непреднамеренной стороны последствия. Существует неотъемлемая напряженность между выражением смысла и избеганием непреднамеренных эффектов, и это напряжение на самом деле происходит от теорем неполноты программирования и нашей вселенной.
Это упрощение, технически неточное и часто двусмысленное, чтобы определить декларативное как " что делать " и необходимо как " как do ". Двусмысленным случаем является" что "- это" как "в программе, которая выводит программу - компилятор.
Очевидно, что неограниченная рекурсия которая делает язык Turing завершен, также аналогична семантике - не только в синтаксической структуре оценки (оперативная семантика a.k.a.). Это логически является примером, аналогичным теореме Гёделя -" любая полная система аксиом также противоречива ". Подумайте о противоречивой странности этой цитаты! Это также пример, демонстрирующий, как выражение семантики не имеет доказуемой границы, поэтому мы не можем доказать 2, что программа (и аналогично ее семантика) останавливается на теореме Хэллинга.
Теоремы о неполноте вытекают из фундаментальной природы нашей Вселенной, которая, как указано во втором Законе Термодинамики, заключается в том, что "энтропия (a.k.a. # независимых возможностей) навсегда стремится к максимуму ". Кодирование и дизайн программы никогда не заканчиваются - она жива! - потому что она пытается удовлетворить потребность в реальном мире, а семантика реального мира всегда меняется и имеет тенденцию к большему количеству возможностей. Люди никогда не перестают открывать новые вещи (включая ошибки в программах;).
Чтобы точно и технически захватить это вышеупомянутое желаемое понятие в этой странной вселенной, у которой нет края (задумайтесь над тем, что" нет "снаружи нашей вселенной), требует краткого, но обманчиво-непростого определения, которое будет звучать некорректно до тех пор, пока это объясняется глубоко.
Определение:
В декларативном свойстве может быть только один возможный набор операторов, который может выражать каждую конкретную модульную семантику.
Обязательным свойством 3 является двойственное, где семантика несовместима по составу и/или может быть выражена вариациями наборов операторов.
Это определение декларативного является явно локальным в семантической области, что означает, что он требует, чтобы модульная семантика сохраняла свое последовательное значение независимо от того, где и как оно создавалось и использовалось в глобальном масштабе. Таким образом, каждая декларативная модульная семантика должна быть внутренне ортогональна всем возможным другим, а не невозможным (из-за теорем неполноты) глобальному алгоритму или модели для подтверждения согласованности, которая также является точкой" Больше не всегда лучше" Роберта Харпера, профессора компьютерных наук в Университете Карнеги Меллона, одного из разработчиков Standard ML.
Примеры этой модульной декларативной семантики включают функторы теории категорий, например. Applicative
, номинальная типизация, пространства имен, именованные поля и w.r.t. к оперативному уровню семантики, тогда чисто функциональное программирование.
Таким образом, хорошо разработанные декларативные языки могут более четко выражать смысл, хотя и с некоторой потерей общности в том, что может быть выражено, но в что может быть выражено с внутренней консистенцией.
Примером вышеупомянутого определения является набор формул в ячейках программы электронных таблиц, которые, как ожидается, не будут давать то же значение при перемещении в разные ячейки столбцов и строк, т.е. изменятся идентификаторы ячеек. Идентификаторы ячеек являются частью и не являются излишними для предполагаемого значения. Таким образом, результат каждой таблицы уникален w.r.t. к идентификаторам ячеек в наборе формул. Согласованная модульная семантика в этом случае - это использование идентификаторов ячеек в качестве входных и выходных данных чистых функций для формул ячеек (см. Ниже).
Язык гипертекстовой маркировки, ака HTML - язык для статических веб-страниц - является примером высоко (но не идеально 3) декларативного языка, который (при не ранее, чем HTML 5) не имел возможности выражать динамическое поведение. HTML - это, пожалуй, самый простой язык для изучения. Для динамического поведения обязательный скриптовый язык, такой как JavaScript, обычно сочетается с HTML. HTML без JavaScript подходит для декларативного определения, потому что каждый номинальный тип (т.е. Теги) сохраняет свое согласованное значение под композицией в рамках правил синтаксиса.
Конкурирующим определением для декларативного является commutative и idempotent свойств семантических операторов, т.е. что операторы могут быть переупорядочены и дублированы без изменения значения. Например, операторы, присваивающие значения именованным полям, могут быть переупорядочены и дублированы без изменения значения программы, если эти имена являются модульными w.r.t. к любому подразумеваемому порядку. Имена иногда подразумевают порядок, например. Идентификаторы ячеек включают в себя их столбцы и позицию в строке - перемещение итоговой таблицы в таблицу изменяет ее значение. В противном случае эти свойства неявно требуют глобальной согласованности семантики. Как правило, невозможно создать семантику операторов, чтобы они оставались согласованными, если они были упорядочены произвольно или дублировались, потому что порядок и дублирование являются неотъемлемой частью семантики. Например, утверждения "Foo exists" (или конструкция) и "Foo не существует" (и уничтожение). Если рассматривать случайную несогласованность в эндемике предполагаемой семантики, то можно принять это определение как достаточно общее для декларативного свойства. По существу это определение пустое как обобщенное определение, поскольку оно пытается сделать согласованность ортогональной семантике, т.е. Игнорировать тот факт, что семантика вселенной динамически неограничена и не может быть захвачена в глобальной парадигме когерентности.
Требование коммутативных и идемпотентных свойств для (порядка структурной оценки) оперативной семантики нижнего уровня преобразует оперативную семантику в декларативную локализованную модульную семантику, например. чистое функциональное программирование (включая рекурсию вместо императивных циклов). Тогда рабочий порядок деталей реализации не влияет (т.е. Глобально распространяется) на согласованность семантики более высокого уровня. Например, порядок оценки (и, теоретически, дублирования) формул электронных таблиц не имеет значения, поскольку выходы не копируются на входы до тех пор, пока не будут вычислены все выходы, то есть аналогичны чистым функциям.
C, Java, С++, С#, PHP и JavaScript не являются особенно декларативными. Синтаксис синтаксиса и синтаксиса Python более декларативно связанный с предполагаемые результаты, т.е. последовательная синтаксическая семантика, которая устраняет посторонние, поэтому можно легко понять код после того, как они его забыли. Copute и Haskell обеспечивают соблюдение детерминизм оперативной семантики и поощрение "не повторять себя "(DRY), потому что они допускают чисто функциональную парадигму.
2 Даже там, где мы можем доказать семантику программы, например. с языком Coq, это ограничивается семантикой, выраженной в типизации, и типизация никогда не может захватить всю семантику программы - даже для языков, которые не являются Тьюрингом, например, с HTML + CSS можно выразить несогласованные комбинации, которые, таким образом, имеют семантику undefined.
3 Многие объяснения неправильно утверждают, что только императивное программирование имеет синтаксически упорядоченные утверждения. Я разъяснил эту путаницу между императивным и функциональным программированием. Например, порядок выражений HTML не уменьшает согласованность их значения.
Изменить: я отправил следующий комментарий в блог Роберта Харпера:
в функциональном программировании... диапазон изменения переменной - это тип
В зависимости от того, как можно отличить функциональность от императивного программирования, ваш "назначаемый в императивной программе" также может иметь тип, устанавливающий привязку к его изменчивости.
Единственное не-запутанное определение, которое я в настоящее время ценю для функционального программирование является а) функционирует как первоклассные объекты и типы, б) предпочтение для рекурсии над циклами и/или в) чистые функции, т.е. те функции, которые не влияют на желаемую семантику программа, когда memoized ( таким образом, совершенно чистый функциональный программирования не существует в общей смысловой семантике из-за воздействия эксплуатационной семантики, например. Память распределениесуб > ).
Идемпотентное свойство чистой функции означает вызов функции на его переменные могут быть заменены его значением, которое обычно не является случай аргументов императивной процедуры. Чистые функции кажутся декларативными w.r.t. к несохраненным переходам состояний между входами и типами результатов.
Но состав чистых функций не поддерживает таких согласованность, поскольку можно моделировать побочный эффект (глобальный state) императивный процесс на чистом функциональном языке программирования, например Haskell IOMonad и, кроме того, полностью невозможно не допускайте таких действий в любом полном функциональном программировании Тьюринга язык.
Как я писал в 2012 году, что похоже на аналогичный консенсус комментарии в ваш недавний блог, что декларативное программирование - это попытка захватить представление о том, что предполагаемая семантика никогда непрозрачный. Примерами непрозрачной семантики являются зависимость от порядка, зависимость от стирания семантики более высокого уровня при операционном семантический слой (например, отбрасывает не конверсии и не генерирует обобщенные данные ограничить семантику более высокого уровня) и зависимость от переменных значений который не может быть проверен (подтвержден правильным) языком программирования.
Таким образом, я пришел к выводу, что только полные языки, не содержащие Тьюринга, могут быть декларативной.
Таким образом, один однозначный и четкий атрибут декларативного языка может заключаться в том, что его выход может быть доказан, чтобы подчиняться некоторому перечислимому набору порождающие правила. Например, для любой конкретной программы HTML (игнорируя различия в том, как интерпретаторы расходятся), который не является сценарием (т.е. не является полным Тьюринга), то его выходная изменчивость может быть перечислим. Или более кратко HTML-программа - это чистая функция его изменчивость. Кроме того, программа электронных таблиц является чистой функцией ее входные переменные.
Итак, мне кажется, что декларативные языки являются антитезой неограниченная рекурсия, т.е. вторая неполная Gödel теорема самореференциальных теорем не может быть доказана.
Леси Лэмпорт написал сказку о том, как Евклид мог бы работал над теоремами неполноты Гёделя, применимыми к математическим доказательствам в контексте языка программирования путем сопоставления между типами и логика (соответствие Карри-Говарда и т.д.).
Ответ 9
Императивное программирование: рассказывать "машине", как что-то делать, и в результате произойдет то, что вы хотите.
Декларативное программирование: расскажите "машине", что вы хотели бы сделать, и дайте компьютеру понять, как это сделать.
Пример императива
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);
}
Примечание. Разница заключается не в краткости, сложности или абстракции. Как указано, разница в том, как и что.
Ответ 10
В настоящее время новый фокус: нам нужны старые классификации?
Императивные/декларативные/функциональные аспекты были хорошими в прошлом для классификации родовых языков, но в настоящее время все "большие языки" (как Java, Python, Javascript и т.д.) имеют некоторый вариант (обычно рамки), чтобы выразить "другим фокусом", чем его основной (обычный императив), и выражать параллельные процессы, декларативные функции, лямбда и т.д.
Итак, хороший вариант этого вопроса: "Какой аспект хорош для классификации фреймворков сегодня?"
... Важным аспектом является то, что мы можем обозначить "стиль программирования"...
Фокусировка на слиянии данных с алгоритмом
Хороший пример для объяснения. Как вы можете прочитать о jQuery в Википедии,
Набор основных функций jQuery - выбор элементов DOM, обход и манипуляция -, активированный его механизмом селектора (...), создал новый "стиль программирования", алгоритмы слияния и структуры данных DOM
Итак, jQuery - лучший (популярный) пример фокусировки на "новом стиле программирования", который не только ориентирован на объекты, " Fusing алгоритмы и структуры данных". jQuery несколько реагирует как электронные таблицы, но не "ориентирован на ячейки", "DOM- node ориентирован"... Сравнение основных стилей в этом контексте:
-
Нет слияния: во всех "больших языках", в любом функциональном/декларативном/императивном выражении, обычным является "отсутствие слияния" данных и алгоритма, за исключением некоторой объектно-ориентированной, то есть слияние в строгая алгебраическая структура.
-
Некоторые слияния: все классические стратегии слияния, в наши дни имеют некоторые рамки, использующие его как парадигму... dataflow, Программирование, управляемое событиями (или старые языки, относящиеся к домену, как awk и XSLT)... Как и при программировании с современными электронными таблицами, они также являются примерами реактивное программирование.
-
Большой слияние: это "стиль jQuery"... jQuery - это язык, специфичный для домена, ориентированный на "алгоритмы слияния" и DOM-структуры данных ".
PS: другие "языки запросов", так как XQuery, SQL (с PL как императивный вариант выражения) также являются примерами алгоритмов слияния данных, но они являются островами, без слияния с другими системными модулями... Spring при использовании предложений find()
-variants и Specification - еще один хороший пример слияния.
Ответ 11
Я думаю, что ваша таксономия неверна. Существует два противоположных типа, обязательные и декларативные. Функциональный - это просто подтип декларативного. Кстати, википедия утверждает тот же факт.
Ответ 12
Декларативное программирование - это программирование, выражая некоторую вечную логику между входом и выходом, например, в псевдокоде, следующий пример будет декларативным:
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, С++, Pascall, C, Fortran, Assembly
Ответ 13
Некоторые хорошие ответы здесь относительно отмеченных "типов".
Я представляю некоторые дополнительные, более "экзотические" концепции, часто связанные с толпой функционального программирования:
- Специфический язык домена или DSL. Программирование: создание нового языка для решения проблемы.
- Мета-программирование: когда ваша программа записывает другие программы.
- Эволюционное программирование: где вы создаете систему, которая постоянно улучшает себя или генерирует последовательно лучшие поколения подпрограмм.
Ответ 14
В двух словах, чем больше стиль программирования подчеркивает What (to do) абстрагирование от деталей How (чтобы сделать это), тем больше этот стиль считается декларативным. Для императива верно обратное. Функциональное программирование связано с декларативным стилем.