Что такое декларативное Программирование? [закрытый]

Я продолжаю слышать этот термин, разбросанный в нескольких разных контекстах. Что это?

18 ответов


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

примерами декларативных языков программирования являются SQL и Prolog.


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

Контексте Независимости

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

забрать yacc в качестве примера. Это генератор парсера ака. компилятор компилятор, внешний декларативный DSL для описания грамматики языка, так что парсер для этого языка может быть автоматически сгенерирован из описания. Из-за своей независимости от контекста вы можете делать много разных вещей с такой грамматикой:

  • создайте синтаксический анализатор C для этой грамматики ( оригинальный вариант использования для yacc)
  • создать синтаксический анализатор C++ для этой грамматики
  • создайте синтаксический анализатор Java для этой грамматики (используя Jay)
  • создайте парсер C# для этой грамматики (используя GPPG)
  • создайте парсер Ruby для этой грамматики (используя Racc)
  • создайте визуализацию дерева для этой грамматики (используя GraphViz)
  • просто сделать некоторые довольно печати, фантазии форматирования и подсветки синтаксиса исходного файла yacc и включить его в свое справочное руководство в качестве синтаксической спецификации вашего языка

и многое другое ...

оптимизация

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

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


свободно:

декларативное Программирование стремится к:-

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

императивное Программирование стремится к:-

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

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


мне жаль, но я должен не согласиться со многими другими ответами. Я хотел бы прекратить это путаное непонимание определения декларативного программирования.

определение

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

другой приведенные атрибуты декларативного программирования, производные от этого RT. Пожалуйста, нажмите гиперссылку выше для подробного объяснения.

таблицы пример

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

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


декларативное программирование-это картина, где императивное программирование-это инструкции для рисования эту картину.

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

когда вы используете XML для разметки данных, вы используете декларативное программирование, потому что вы говорите: "это человек, это день рождения, а вон там улица адрес."

некоторые примеры, где декларативное и императивное Программирование объединяются для большего эффекта:

  • Windows Presentation Foundation использует декларативный синтаксис XML для описания внешнего вида пользовательского интерфейса и связей (Привязок) между элементами управления и базовыми структурами данных.

  • структурированные файлы конфигурации используют декларативный синтаксис (так же просто, как пары "ключ=значение"), чтобы определить, что строка или значение данных.

  • HTML помечает текст тегами, описывающими роль каждого фрагмента текста по отношению ко всему документу.


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

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

Это своего рода декларативное Программирование. Вы объявляете пространство задач и решение, а не поток программы.

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


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

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

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

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

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

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

очевидно неограниченная рекурсия, которая делает язык Тьюринга полным, также аналогично в семантике-не только в синтаксической структуре оценки (a.к. a. операционная семантика). Логически это пример, аналогичный теореме Геделя:--8-->любая полная система аксиомы также непоследовательны". Поразмыслите над противоречивой странностью этой цитаты! Это также пример, который демонстрирует, как выражение семантики не имеет доказуемой границы, поэтому мы не можем доказать2 что программа (и аналогично ее семантика) останавливает a.к. a. теорема остановки.

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

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

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


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

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


это определение декларативного является отчетливо местные в семантической области, что означает, что он требует, чтобы модульная семантика поддерживала свое согласованное значение независимо от того, где и как она создается и используется в глобальные объем. Таким образом, каждая декларативная модульная семантика должна быть внутренне ортогональна всем возможным другие-и не невозможные (из-за неполноты теорем) глобальные алгоритм или модель для свидетельствования согласованности, которая также является точкой"Больше Не Всегда Лучше" Роберт Харпер, профессор информатики в Университете Карнеги-Меллона, один из дизайнеров Standard ML.

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

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

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

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

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

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

C, Java, C++, C#, PHP и JavaScript не являются особенно декларативными. Синтаксис Copute и синтаксис Python являются более декларативными в сочетании с ожидаемые результаты, т. е. последовательная синтаксическая семантика, которая устраняет постороннее, поэтому можно без труда понять код после того, как они его забыли. Copute и Haskell детерминизм операционной семантики и поощрение "не повторяйте себя!--3--> " (сухой), потому что они позволяют только чистую функциональную парадигму.


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

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


Edit: я опубликовал комментарий в блог Роберта Харпера:

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

в зависимости от того, как отличить функциональное от императивного Программирование, ваше " назначаемое’ в императивной программе также может иметь тип, устанавливающий границу своей изменчивости.

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

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

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

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

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

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

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

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


Я уточнил свое понимание декларативного программирования, начиная с декабря 2011 года, когда я предоставил ответ на этот вопрос. Здесь следует мое нынешнее понимание.

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

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

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

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

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

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


декларативное программирование-это программирование с объявлениями, т. е. декларативными предложениями. Декларативные предложения обладают рядом свойств, отличающих их от императивных предложений. В частности, декларации:

  • коммутативный (может быть переупорядочен)
  • ассоциативный (можно перегруппировать)
  • идемпотент (может повторяться без изменения значения)
  • монотонный (объявления не вычитают информацию)

A важным моментом является то, что все они являются структурными свойствами и ортогональны предмету. Декларативный не о "что и как". Мы можем объявить (представлять и ограничивать) a "как" так же легко, как мы объявляем "как". декларативный - это структура, а не содержание. декларативное Программирование оказывает существенное влияние на то, как мы абстрагируемся и рефакторинг, и как нам распределить ее на подпрограммы, но не на столько модель предметной области.

часто мы можем преобразовать из императивного в декларативный, добавив контекст. Е. Г. из "поверните налево. (... подожди ...) поворачивать направо."to" Боб повернет налево на пересечении Foo и Bar в 11: 01. Боб повернет направо на пересечении бар и баз в 11: 06."Обратите внимание, что в последнем случае предложения являются идемпотентными и коммутативными, в то время как в первом случае перестановка или повторение предложений серьезно изменит значение программа.

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


вот пример.

в CSS (используется для стиля HTML-страниц), если вы хотите, чтобы элемент изображения был 100 пикселей в высоту и 100 пикселей в ширину, вы просто "объявляете", что это то, что вы хотите следующим образом:

#myImageId {
height: 100px;
width: 100px;
}

вы можете считать CSS декларативным языком "таблицы стилей".

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

их уникальные реализации, конечно, написаны не на декларативном языке, а на процедурном, таком как Assembly, C, C++, Java, JavaScript или Python. Этот код представляет собой набор шагов, которые должны выполняться шаг за шагом (и могут включать вызовы функций). Он может делать такие вещи, как интерполяция значений пикселей и визуализация на экране.


Это метод программирования, основанный на описании что что-то должен делать или быть вместо описания как он должен работать.

другими словами, вы не пишете алгоритмы, сделанные из выражений, вы просто макет, как вы хотите, чтобы все было. Два хороших примера-HTML и WPF.

эта статья в Википедии-хороший обзор:http://en.wikipedia.org/wiki/Declarative_programming


описание компьютеру, что вы хотите, а не как что-то сделать.


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


Я бы объяснил это, как DP-это способ выразить

  • A выражение цели, условия - то, что мы ищем. Есть один, может быть, или много?
  • некоторые известные факты
  • правила, которые расширяют знать факты

...и где есть вычет двигатель обычно работает с объединение алгоритм поиска целей.


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

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

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

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


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

Это все больше означает очень мало, так как он имеет определение, данное пользователями выше. Должно быть ясно, что существует пропасть между декларативным программированием Haskell, в отличие от декларативного программирования HTML.


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

  • ASP.Net разметка для привязки данных. Он просто говорит "заполните эту сетку этим источником", например, и оставляет ее системе для того, как это происходит.
  • выражения Linq

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

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

foreach (object item in MyList)
{
   DoSomething(item);
}

ничего особенного. Но что, если вы используете более декларативный синтаксис и вместо этого определяете DoSomething () как действие? Тогда вы можете сказать это так:

MyList.ForEach(DoSometing);

Это, конечно, более лаконично. Но я уверен, что у вас есть больше проблем, чем просто сохранение двух строк кода здесь и там. Например, производительность. Старый способ, обработка должна была быть сделана в последовательность. Что, если ...Метод ForEach () имел способ для вас сигнализировать, что он может обрабатывать обработку параллельно, автоматически? Теперь внезапно вы сделали свой код многопоточным очень безопасным способом и изменили только одну строку кода. И, на самом деле, есть an расширение для .Net, который позволяет вам делать именно это.

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

Это зависит от того, как вы отправите ответ в тексте. В целом вы можете смотреть на программу с определенным видом, но это зависит от того, под каким углом вы смотрите на проблему. Я дам вам начать с программы: Тусклый Автобус, Автомобиль, Время, Высота Как Integr

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