Was ist deklarative Programmierung? [geschlossen]


193

Ich höre immer wieder, wie dieser Begriff in verschiedenen Kontexten herumgeworfen wird. Was ist es?


7
Die Antwort, die Sie als richtig ausgewählt haben (angezeigt durch das grüne Häkchen), ist falsch. Es definiert nicht, was deklarative Programmierung von ihrer Antithese unterscheidet - imperative Programmierung. Bitte ändern Sie Ihre Auswahl.
Shelby Moore III

3
Ja, die als richtig gekennzeichnete Antwort ist NICHT richtig.
Dermot

4
@ShelbyMooreIII Geben Sie auch an, welche Antwort richtig ist, damit wir sie lesen können!
vivek.m

@ vivek.m Ich habe heute eine neue Antwort gegeben .
Shelby Moore III

Antworten:


148

Deklarative Programmierung ist, wenn Sie Ihren Code so schreiben, dass er beschreibt, was Sie tun möchten und nicht, wie Sie es tun möchten. Es bleibt dem Compiler überlassen, das Wie herauszufinden.

Beispiele für deklarative Programmiersprachen sind SQL und Prolog.


29
Sie müssen noch herausfinden, "wie" Sie dem Computer sagen, "was" Sie wollen :)
hasen

7
@hasenj Diese und die anderen Antworten definieren nicht das einzige Attribut, das nicht mit der imperativen Programmierung geteilt wird - nämlich Unveränderlichkeit .
Shelby Moore III

3
Es ist wirklich großartig, wenn Sie erwähnen können, wie es sich von der imperativen Programmierung unterscheidet (Sprachen wie C, C ++, C #), dann wird es für die Leser einfacher, den Unterschied zu erkennen.
RBT

1
Programmierer : "Ich möchte nach Paris reisen." deklarativ (c) : "Wie möchten Sie dorthin gelangen? Mit dem Boot segeln? oder in einem Flugzeug fliegen? Vielleicht auf halber Strecke segeln und dann den Rest des Weges dorthin fliegen?" Programmierer : "Ich habe kein Interesse daran, wie es gemacht wird." Imperativ (SQL) : "Keine Sorge. Ich kann nachfragen, was Sie brauchen." ( So verstehe ich die Antwort )
nate

Wie kann SQL deklarativ sein, wenn es Ausdrücke unterstützt, die nicht referenziell transparent sind?
Java-Addict301

80

Die anderen Antworten machen bereits einen fantastischen Job und erklären, was deklarative Programmierung ist. Deshalb werde ich nur einige Beispiele dafür nennen, warum dies nützlich sein könnte.

Kontextunabhängigkeit

Deklarative Programme sind kontextunabhängig . Da sie nur das endgültige Ziel angeben, nicht jedoch die Zwischenschritte, um dieses Ziel zu erreichen, kann dasselbe Programm in verschiedenen Kontexten verwendet werden. Dies ist bei imperativen Programmen schwierig , da sie häufig vom Kontext abhängen (z. B. versteckter Zustand).

Nehmen Sie yaccals Beispiel. Es ist ein Parser-Generator aka. Compiler Compiler, ein externes deklaratives DSL zur Beschreibung der Grammatik einer Sprache, sodass aus der Beschreibung automatisch ein Parser für diese Sprache generiert werden kann. Aufgrund seiner Kontextunabhängigkeit können Sie mit einer solchen Grammatik viele verschiedene Dinge tun:

  • Generieren Sie einen C-Parser für diese Grammatik (der ursprüngliche Anwendungsfall für yacc)
  • Generieren Sie einen C ++ - Parser für diese Grammatik
  • Generieren Sie einen Java-Parser für diese Grammatik (mit Jay)
  • Generieren Sie einen C # -Parser für diese Grammatik (mit GPPG).
  • Generieren Sie einen Ruby-Parser für diese Grammatik (mit Racc)
  • Generieren Sie eine Baumvisualisierung für diese Grammatik (mit GraphViz).
  • Führen Sie einfach einige hübsche Druck-, Formatierungs- und Syntaxhervorhebungen für die yacc-Quelldatei selbst durch und fügen Sie sie als syntaktische Spezifikation Ihrer Sprache in Ihr Referenzhandbuch ein

Und viele mehr …

Optimierung

Da Sie dem Computer nicht vorschreiben, welche Schritte in welcher Reihenfolge ausgeführt werden sollen, kann er Ihr Programm viel freier anordnen und möglicherweise sogar einige Aufgaben parallel ausführen. Ein gutes Beispiel ist ein Abfrageplaner und Abfrageoptimierer für eine SQL-Datenbank. In den meisten SQL-Datenbanken können Sie die Abfrage anzeigen, die sie tatsächlich ausführen, im Vergleich zu der Abfrage, zu deren Ausführung Sie sie aufgefordert haben. Oft sehen diese Abfragen nicht aussich mögen. Der Abfrageplaner berücksichtigt Dinge, von denen Sie nicht einmal geträumt hätten: beispielsweise die Rotationslatenz des Plattentellers oder die Tatsache, dass eine völlig andere Anwendung für einen völlig anderen Benutzer gerade eine ähnliche Abfrage und die Tabelle ausgeführt hat, die Sie sind Beitritt mit und dass Sie so hart gearbeitet haben, um das Laden zu vermeiden, ist sowieso schon im Speicher.

Hier gibt es einen interessanten Kompromiss: Die Maschine muss härter arbeiten, um herauszufinden, wie etwas zu tun ist, als dies in einer zwingenden Sprache der Fall wäre, aber wenn sie es herausfindet, hat sie viel mehr Freiheit und viel mehr Informationen für die Optimierung Bühne.


23

Lose:

Deklarative Programmierung tendiert zu: -

  • Sätze von Deklarationen oder deklarativen Anweisungen, von denen jede eine Bedeutung hat (häufig im Problembereich) und unabhängig und isoliert verstanden werden kann.

Imperative Programmierung tendiert zu: -

  • Befehlssequenzen, von denen jede eine Aktion ausführt; aber was kann oder kann nicht Bedeutung in der Problemdomäne haben.

Infolgedessen hilft ein imperativer Stil dem Leser, die Mechanik dessen zu verstehen, was das System tatsächlich tut, gibt jedoch möglicherweise nur wenig Einblick in das Problem, das es lösen soll. Auf der anderen Seite hilft ein deklarativer Stil dem Leser, die Problemdomäne und den Ansatz des Systems zur Lösung des Problems zu verstehen, ist jedoch in Bezug auf die Mechanik weniger informativ.

Bei echten Programmen (auch solchen, die in Sprachen geschrieben sind, die die Enden des Spektrums bevorzugen, wie ProLog oder C) sind beide Stile an verschiedenen Stellen in unterschiedlichem Maße vorhanden, um den unterschiedlichen Komplexitäten und Kommunikationsanforderungen des Stücks gerecht zu werden. Ein Stil ist dem anderen nicht überlegen; Sie dienen nur unterschiedlichen Zwecken, und wie bei vielen Dingen im Leben ist Mäßigung der Schlüssel.


Das ist die richtige Antwort. Nichts von diesem Murmeln oben
Krzysztof Wende

Vielen Dank, dass Sie nicht nur die Frage beantwortet haben, sondern auch den "Explain Like I'm 5" -Stil mit Kontext und Praktikabilität. Hervorragende Antwort.
Montag,

17

Hier ist ein Beispiel.

Wenn Sie in CSS (zum Stylen von HTML-Seiten) möchten, dass ein Bildelement 100 Pixel hoch und 100 Pixel breit ist, "deklarieren" Sie einfach, dass dies wie folgt gewünscht wird:

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

Sie können CSS als deklarative "Stylesheet" -Sprache betrachten.

Die Browser-Engine, die dieses CSS liest und interpretiert , kann das Bild so groß und breit erscheinen lassen, wie es möchte. Verschiedene Browser-Engines (z. B. die Engine für IE, die Engine für Chrome) implementieren diese Aufgabe unterschiedlich.

Ihre einzigartigen Implementierungen sind natürlich NICHT in einer deklarativen Sprache geschrieben, sondern in einer prozeduralen wie Assembly, C, C ++, Java, JavaScript oder Python. Dieser Code besteht aus einer Reihe von Schritten, die Schritt für Schritt ausgeführt werden müssen (und möglicherweise Funktionsaufrufe enthalten). Es kann beispielsweise Pixelwerte interpolieren und auf dem Bildschirm rendern.


11

Es tut mir leid, aber ich muss vielen anderen Antworten nicht zustimmen. Ich möchte dieses durcheinandergebrachte Missverständnis der Definition der deklarativen Programmierung stoppen.

Definition

Die referenzielle Transparenz (RT) der Unterausdrücke ist das einzige erforderliche Attribut eines deklarativen Programmierausdrucks , da es das einzige Attribut ist, das nicht mit der imperativen Programmierung geteilt wird.

Andere zitierte Attribute der deklarativen Programmierung leiten sich aus dieser RT ab. Bitte klicken Sie auf den Hyperlink oben für die detaillierte Erklärung.

Beispiel für eine Tabellenkalkulation

Zwei Antworten erwähnten die Tabellenkalkulationsprogrammierung. In den Fällen, in denen die Tabellenkalkulationsprogrammierung (auch als Formeln bezeichnet) nicht auf den veränderlichen globalen Status zugreift , handelt es sich um eine deklarative Programmierung. Dies liegt daran, dass die veränderlichen Zellenwerte die monolithische Eingabe und Ausgabe von main()(dem gesamten Programm) sind. Die neuen Werte werden nach Ausführung jeder Formel nicht in die Zellen geschrieben, sodass sie für die Lebensdauer des deklarativen Programms (Ausführung aller Formeln in der Tabelle) nicht veränderbar sind. Daher betrachten die Formeln diese veränderlichen Zellen relativ zueinander als unveränderlich. Eine RT-Funktion kann auf den unveränderlichen globalen Status (und auch auf den veränderlichen lokalen Status ) zugreifen .

Die Fähigkeit, die Werte in den Zellen zu mutieren, wenn das Programm beendet wird (als Ausgabe von main()), macht sie daher nicht zu veränderlichen gespeicherten Werten im Kontext der Regeln. Der Hauptunterschied besteht darin, dass die Zellenwerte nicht aktualisiert werden, nachdem jede Tabellenkalkulationsformel ausgeführt wurde. Daher spielt die Reihenfolge der Ausführung der Formeln keine Rolle. Die Zellenwerte werden aktualisiert, nachdem alle deklarativen Formeln ausgeführt wurden.


1
Unbeabsichtigte Nebenwirkungen können die Beziehung zwischen dem, was deklariert wurde, und dem tatsächlichen Verhalten des Programms zerstören. Ich habe dies in einer neuen Antwort ausführlicher erklärt .
Shelby Moore III

8

Deklarative Programmierung ist das Bild, wobei imperative Programmierung Anweisungen zum Malen dieses Bildes sind.

Sie schreiben in einem deklarativen Stil, wenn Sie "sagen, was es ist", anstatt die Schritte zu beschreiben, die der Computer unternehmen sollte, um dorthin zu gelangen, wo Sie es möchten.

Wenn Sie XML zum Markieren von Daten verwenden, verwenden Sie deklarative Programmierung, weil Sie sagen: "Dies ist eine Person, das ist ein Geburtstag, und dort drüben gibt es eine Adresse."

Einige Beispiele dafür, wo deklarative und imperative Programmierung kombiniert werden, um eine größere Wirkung zu erzielen:

  • Windows Presentation Foundation verwendet die deklarative XML-Syntax, um zu beschreiben, wie eine Benutzeroberfläche aussieht und welche Beziehungen (Bindungen) zwischen Steuerelementen und zugrunde liegenden Datenstrukturen bestehen.

  • Strukturierte Konfigurationsdateien verwenden deklarative Syntax (so einfach wie "Schlüssel = Wert" -Paare), um zu identifizieren, was eine Zeichenfolge oder ein Wert von Daten bedeutet.

  • HTML markiert Text mit Tags, die beschreiben, welche Rolle jeder Text in Bezug auf das gesamte Dokument spielt.


2
Obwohl XML deklarativ ist, würde ich nicht sagen, dass es deklarative Programmierung ist, nur weil dem Markup keine aktive Semantik zugeordnet ist. Zu sagen, dass etwas eine Adresse ist, hilft nicht dabei, herauszufinden, was Sie damit machen möchten.
HenryR

1
Es muss einen zugrunde liegenden Kontext (Domäne?) Geben, in dem das deklarative Programm verwendet wird. Die Verwendung von XML in Kombination mit ANT kann daher als deklaratives Programm ausgelegt werden.
Gutzofter

7

Deklarative Programmierung ist das Programmieren mit Deklarationen, dh deklarativen Sätzen. Deklarative Sätze haben eine Reihe von Eigenschaften, die sie von imperativen Sätzen unterscheiden. Erklärungen sind insbesondere:

  • kommutativ (kann nachbestellt werden)
  • assoziativ (kann neu gruppiert werden)
  • idempotent (kann ohne Änderung der Bedeutung wiederholen)
  • monoton (Erklärungen subtrahieren keine Informationen)

Ein relevanter Punkt ist, dass dies alles strukturelle Eigenschaften sind und orthogonal zum Gegenstand sind. Bei der Erklärung geht es nicht um "Was gegen Wie" . Wir können ein "Wie" genauso einfach deklarieren (darstellen und einschränken) wie ein "Was" . Bei der Erklärung geht es um Struktur, nicht um Inhalt. Die deklarative Programmierung hat einen erheblichen Einfluss darauf, wie wir unseren Code abstrahieren und umgestalten und wie wir ihn in Unterprogramme modularisieren, jedoch nicht so sehr auf das Domänenmodell.

Oft können wir durch Hinzufügen von Kontext von Imperativ zu Deklarativ konvertieren. ZB von "Biegen Sie links ab. (... warten Sie ...) Biegen Sie rechts ab." zu "Bob wird an der Kreuzung von Foo und Bar um 11:01 Uhr links abbiegen. Bob wird an der Kreuzung von Bar und Baz um 11:06 Uhr rechts abbiegen." Beachten Sie, dass im letzteren Fall die Sätze idempotent und kommutativ sind, während im ersten Fall das Umordnen oder Wiederholen der Sätze die Bedeutung des Programms stark verändern würde.

In Bezug auf Monotonie können Deklarationen Einschränkungen hinzufügen , die Möglichkeiten subtrahieren . Einschränkungen fügen jedoch weiterhin Informationen hinzu (genauer gesagt, Einschränkungen sind Informationen). Wenn wir zeitvariable Deklarationen benötigen, ist es typisch, dies mit expliziter zeitlicher Semantik zu modellieren - z. B. von "der Ball ist flach" bis "der Ball ist zum Zeitpunkt T flach". Wenn wir zwei widersprüchliche Deklarationen haben, haben wir ein inkonsistentes deklaratives System, obwohl dies durch die Einführung weicher Einschränkungen (Prioritäten, Wahrscheinlichkeiten usw.) oder die Nutzung einer parakonsistenten Logik gelöst werden kann .


1
Deklarative Ausdrücke tragen zum beabsichtigten Verhalten des Programms bei, Imperative können zum beabsichtigten oder unbeabsichtigten Verhalten beitragen. Deklarativ muss nicht kommutativ und idempotent sein, wenn dies absichtliche Semantik ist.
Shelby Moore III

6

Beschreiben eines Computers, was Sie wollen, nicht wie man etwas macht.


6

Stellen Sie sich eine Excel-Seite vor. Mit Spalten, die mit Formeln gefüllt sind, um Ihre Steuererklärung zu berechnen.

Die gesamte Logik wird in den Zellen deklariert. Die Reihenfolge der Berechnung erfolgt durch die Formel selbst und nicht prozedural.

Darum geht es bei der deklarativen Programmierung. Sie deklarieren den Problemraum und die Lösung und nicht den Programmablauf.

Prolog ist die einzige deklarative Sprache, die ich benutze. Es erfordert eine andere Art des Denkens, aber es ist gut zu lernen, wenn Sie nur etwas anderem als der typischen prozeduralen Programmiersprache ausgesetzt werden.


6

Ich habe mein Verständnis der deklarativen Programmierung seit Dezember 2011 verfeinert, als ich eine Antwort auf diese Frage gab. Hier folgt mein aktuelles Verständnis.

Die lange Version meines Verständnisses (Forschung) finden Sie unter diesem Link , den Sie lesen sollten, um ein tiefes Verständnis der Zusammenfassung zu erhalten, die ich unten bereitstellen werde.

Bei der imperativen Programmierung wird der veränderbare Zustand gespeichert und gelesen. Daher kann die Reihenfolge und / oder das Duplizieren von Programmanweisungen das Verhalten (die Semantik) des Programms ändern (und sogar einen Fehler verursachen, dh unbeabsichtigtes Verhalten).

Im naivsten und extremsten Sinne (was ich in meiner vorherigen Antwort behauptet habe) vermeidet die deklarative Programmierung (DP) jeden gespeicherten veränderlichen Zustand, so dass die Reihenfolge und / oder Vervielfältigung von Programmanweisungen das Verhalten (die Semantik) des Programms NICHT ändern kann .

Eine solch extreme Definition wäre jedoch in der realen Welt nicht sehr nützlich, da fast jedes Programm einen gespeicherten veränderlichen Zustand beinhaltet. Das Tabellenkalkulationsbeispiel entspricht dieser extremen Definition von DP, da der gesamte Programmcode mit einer statischen Kopie des Eingabestatus vollständig ausgeführt wird, bevor die neuen Status gespeichert werden. Wenn dann ein Zustand geändert wird, wird dies wiederholt. Die meisten Programme der realen Welt können jedoch nicht auf ein solches monolithisches Modell von Zustandsänderungen beschränkt werden.

Eine nützlichere Definition von DP ist, dass die Reihenfolge und / oder Vervielfältigung von Programmieranweisungen keine undurchsichtige Semantik ändert. Mit anderen Worten, es treten keine versteckten zufälligen Änderungen in der Semantik auf - Änderungen in der Reihenfolge der Programmanweisungen und / oder Duplikationen verursachen nur beabsichtigte und transparente Änderungen des Programmverhaltens.

Der nächste Schritt wäre, darüber zu sprechen, welche Programmiermodelle oder Paradigmen bei DP helfen, aber das ist hier nicht die Frage.


Update: Bitte beziehen Sie sich auch auf die ausführlichere Erklärung in meiner anderen Antwort zur Definition der deklarativen Programmierung.
Shelby Moore III

Functional programmingist heutzutage ein Modewort, das im Wesentlichen eine Teilmenge der deklarativen Programmierung ist. LINQ in C # -Sprache ist ein Element der funktionalen Programmierung, wenn die Sprache selbst von Natur aus unerlässlich ist. Nach dieser Definition wird C # also zu einer Art Hybrid.
RBT

1
Der Link compute.com ist tot.
Kedar Mhaswade

5

Es ist eine Programmiermethode, die darauf basiert, zu beschreiben, was etwas tun oder sein soll, anstatt zu beschreiben, wie es funktionieren soll.

Mit anderen Worten, Sie schreiben keine Algorithmen aus Ausdrücken, sondern legen nur fest, wie die Dinge sein sollen. Zwei gute Beispiele sind HTML und WPF.

Dieser Wikipedia-Artikel bietet einen guten Überblick: http://en.wikipedia.org/wiki/Declarative_programming


1
Kleiner Streit. WPF ist eine Bibliothek, nicht wirklich eine Sprache oder ein Paradigma. Ich denke, Sie wollten wirklich sagen, dass XAML ein Beispiel für deklarative Sprache ist.
Nick

Und wie würden Sie die Programmierung mit einer Bibliothek / einem Framework beschreiben?
Gutzofter

Es ist falsch zu behaupten, dass deklarative Programmierung keine Ausdrücke enthalten darf. Der Hauptunterschied besteht darin, dass die Ausdrücke gespeicherte Werte nicht mutieren können .
Shelby Moore III

HTML ist keine Programmiersprache
Lud

5

Seit ich meine vorherige Antwort geschrieben habe, habe ich eine neue Definition der deklarativen Eigenschaft formuliert, die unten zitiert wird. Ich habe auch imperative Programmierung als die duale Eigenschaft definiert.

Diese Definition ist der in meiner vorherigen Antwort angegebenen überlegen, da sie prägnant und allgemeiner ist. Es kann jedoch schwieriger sein, etwas zu verstehen, da die Implikation der Unvollständigkeitssätze, die für die Programmierung und das Leben im Allgemeinen gelten, für den Menschen schwierig ist, sich Gedanken zu machen.

In der zitierten Erklärung der Definition wird die Rolle der reinen funktionalen Programmierung bei der deklarativen Programmierung erörtert .

Deklarativ vs. Imperativ

Die deklarative Eigenschaft ist seltsam, stumpf und schwer in einer technisch präzisen Definition zu erfassen, die allgemein und nicht mehrdeutig bleibt, da es eine naive Vorstellung ist, dass wir die Bedeutung (auch bekannt als Semantik) des Programms deklarieren können, ohne dass unbeabsichtigte Nebenwirkungen auftreten. Es gibt eine inhärente Spannung zwischen dem Ausdruck von Bedeutung und der Vermeidung unbeabsichtigter Effekte, und diese Spannung ergibt sich tatsächlich aus den Unvollständigkeitssätzen der Programmierung und unseres Universums.

Es ist zu einfach, technisch ungenau und oft nicht eindeutig, deklarativ als was zu tun ist und zwingend als wie zu tun “ zu definieren . Ein mehrdeutiger Fall ist das „ Was “ ist das „ Wie “ in einem Programm, das ein Programm ausgibt - einen Compiler.

Offensichtlich ist die unbegrenzte Rekursion, die eine Sprache Turing vervollständigt , auch analog in der Semantik - nicht nur in der syntaktischen Struktur der Bewertung (auch bekannt als operative Semantik). Dies ist logischerweise ein Beispiel analog zu Gödels Theorem: „Jedes vollständige Axiomensystem ist auch inkonsistent. “ Denken Sie über die widersprüchliche Verrücktheit dieses Zitats nach! Es ist auch ein Beispiel , das zeigt , wie der Ausdruck der Semantik nicht beweisbar gebunden hat, so können wir nicht beweisen , 2 , dass ein Programm (und seine Semantik analog) halt auch bekannt als der Halting Satz.

Die Unvollständigkeitssätze leiten sich aus der fundamentalen Natur unseres Universums ab, die, wie im zweiten Hauptsatz der Thermodynamik angegeben, lautet: „ Die Entropie (auch bekannt als die Anzahl der unabhängigen Möglichkeiten) tendiert für immer zum Maximum “. Das Codieren und Entwerfen eines Programms ist nie abgeschlossen - es lebt! -, weil es versucht, auf ein Bedürfnis der realen Welt einzugehen, und die Semantik der realen Welt sich ständig ändert und zu mehr Möglichkeiten tendiert. Menschen hören nie auf, neue Dinge zu entdecken (einschließlich Fehler in Programmen ;-).

Um diesen oben erwähnten gewünschten Begriff innerhalb dieses seltsamen Universums, das keinen Rand hat (denken Sie darüber nach! Es gibt kein „Äußeres“ unseres Universums), präzise und technisch zu erfassen, ist eine knappe, aber täuschend nicht einfache Definition erforderlich, die falsch klingt, bis sie erklärt wird tief.

Definition:


In der deklarativen Eigenschaft kann es nur einen möglichen Satz von Anweisungen geben, die jede spezifische modulare Semantik ausdrücken können.

Die imperative Eigenschaft 3 ist das Duale, bei dem die Semantik unter der Zusammensetzung inkonsistent ist und / oder mit Variationen von Aussagen ausgedrückt werden kann.


Diese Definition von deklarativ ist im semantischen Bereich eindeutig lokal , was bedeutet, dass eine modulare Semantik ihre konsistente Bedeutung beibehalten muss, unabhängig davon, wo und wie sie im globalen Bereich instanziiert und verwendet wird . Daher sollte jede deklarative modulare Semantik inhärent orthogonal zu allen möglichen anderen sein - und kein unmöglicher (aufgrund von Unvollständigkeitssätzen) globaler Algorithmus oder Modell, um Konsistenz zu bezeugen , was auch der Punkt von „ Mehr ist nicht immer besser “ von Robert Harper, Professor, ist of Computer Science an der Carnegie Mellon University, einem der Designer von Standard ML.

Beispiele für diese modulare deklarative Semantik sind kategorietheoretische Funktoren, z. B. dieApplicative nominale Typisierung, Namespaces, benannte Felder und die Semantik auf operativer Ebene der Semantik, dann reine funktionale Programmierung.

So können gut gestaltete deklarative Sprachen die Bedeutung klarer ausdrücken , wenn auch mit einem gewissen Verlust an Allgemeinheit in dem, was ausgedrückt werden kann, und einem Gewinn in dem, was mit intrinsischer Konsistenz ausgedrückt werden kann.

Ein Beispiel für die oben genannte Definition ist der Satz von Formeln in den Zellen eines Tabellenkalkulationsprogramms, von denen nicht erwartet wird, dass sie dieselbe Bedeutung haben, wenn sie in verschiedene Spalten- und Zeilenzellen verschoben werden, dh die Zellkennungen werden geändert. Die Zellkennungen sind Teil der beabsichtigten Bedeutung und nicht überflüssig. Daher ist jedes Tabellenkalkulationsergebnis für die Zellkennungen in einer Reihe von Formeln eindeutig. Die konsistente modulare Semantik ist in diesem Fall die Verwendung von Zellkennungen als Eingabe und Ausgabe von reinen Funktionen für Zellformeln (siehe unten).

Die Hyper Text Markup Language alias HTML - die Sprache für statische Webseiten - ist ein Beispiel für eine hoch (aber nicht perfekt 3 ) deklarative Sprache, die (zumindest vor HTML 5) kein dynamisches Verhalten ausdrücken konnte. HTML ist vielleicht die am einfachsten zu erlernende Sprache. Für dynamisches Verhalten wurde normalerweise eine zwingende Skriptsprache wie JavaScript mit HTML kombiniert. HTML ohne JavaScript passt zur deklarativen Definition, da jeder nominelle Typ (dh die Tags) seine konsistente Bedeutung unter Komposition innerhalb der Regeln der Syntax beibehält.

Eine konkurrierende Definition für deklarativ sind die kommutativen und idempotenten Eigenschaften der semantischen Anweisungen, dh, Anweisungen können neu geordnet und dupliziert werden, ohne die Bedeutung zu ändern. Beispielsweise können Anweisungen, die benannten Feldern Werte zuweisen, neu angeordnet und dupliziert werden, ohne die Bedeutung des Programms zu ändern, wenn diese Namen in einer impliziten Reihenfolge modular aufgebaut sind. Namen implizieren manchmal eine Reihenfolge, z. B. enthalten Zellkennungen ihre Spalten- und Zeilenposition. Wenn Sie eine Summe in der Tabelle verschieben, ändert sich ihre Bedeutung. Andernfalls erfordern diese Eigenschaften implizit globalKonsistenz der Semantik. Es ist im Allgemeinen unmöglich, die Semantik von Anweisungen so zu gestalten, dass sie konsistent bleiben, wenn sie zufällig angeordnet oder dupliziert werden, da Reihenfolge und Duplizierung der Semantik eigen sind. Zum Beispiel die Aussagen "Foo existiert" (oder Konstruktion) und "Foo existiert nicht" (und Zerstörung). Wenn man zufällige Inkonsistenzen als endemisch für die beabsichtigte Semantik betrachtet, akzeptiert man diese Definition als allgemein genug für die deklarative Eigenschaft. Im Wesentlichen ist diese Definition als verallgemeinerte Definition leer, weil sie versucht, die Konsistenz orthogonal zur Semantik zu machen, dh der Tatsache zu trotzen, dass das Universum der Semantik dynamisch unbegrenzt ist und nicht in einem globalen Kohärenzparadigma erfasst werden kann .

Das Erfordernis der kommutativen und idempotenten Eigenschaften für die (strukturelle Bewertungsreihenfolge der) Betriebssemantik der unteren Ebene konvertiert die Betriebssemantik in eine deklarative lokalisierte modulare Semantik, z. B. reine funktionale Programmierung (einschließlich Rekursion anstelle von Imperativschleifen). Dann wirkt sich die Betriebsreihenfolge der Implementierungsdetails nicht auf die Konsistenz der übergeordneten Semantik aus (dh global verteilt ). Zum Beispiel spielt die Reihenfolge der Auswertung (und theoretisch auch der Vervielfältigung) der Tabellenkalkulationsformeln keine Rolle, da die Ausgaben erst in die Eingaben kopiert werden, nachdem alle Ausgaben berechnet wurden, dh analog zu reinen Funktionen.

C, Java, C ++, C #, PHP und JavaScript sind nicht besonders deklarativ. Die Syntax von Copute und die Syntax von Python sind deklarativer an die beabsichtigten Ergebnisse gekoppelt , dh an eine konsistente syntaktische Semantik, die das Fremde eliminiert, sodass man Code leicht verstehen kann, nachdem man ihn vergessen hat. Copute und Haskell erzwingen den Determinismus der operativen Semantik und ermutigen dazu, sich nicht zu wiederholen (DRY), weil sie nur das reine Funktionsparadigma zulassen.


2 Selbst wenn wir die Semantik eines Programms beweisen können, z. B. mit der Sprache Coq, ist dies auf die Semantik beschränkt, die in der Eingabe ausgedrückt wird , und die Eingabe kann niemals die gesamte Semantik eines Programms erfassen - nicht einmal für Sprachen, die es sind nicht vollständig, z. B. mit HTML + CSS, ist es möglich, inkonsistente Kombinationen auszudrücken, die somit eine undefinierte Semantik haben.

3 Viele Erklärungen behaupten fälschlicherweise, dass nur die imperative Programmierung syntaktisch geordnete Anweisungen enthält. Ich habe diese Verwechslung zwischen imperativer und funktionaler Programmierung geklärt . Beispielsweise verringert die Reihenfolge der HTML-Anweisungen nicht die Konsistenz ihrer Bedeutung.


Bearbeiten: Ich habe den folgenden Kommentar in Robert Harpers Blog gepostet :

in der funktionalen Programmierung ... ist der Variationsbereich einer Variablen ein Typ

Abhängig davon, wie man funktionale von imperativer Programmierung unterscheidet, kann Ihr 'zuweisbar' in einem imperativen Programm auch einen Typ haben, der seine Variabilität begrenzt.

Die einzige nicht durcheinandergebrachte Definition, die ich derzeit für die funktionale Programmierung schätze, ist a) Funktionen als erstklassige Objekte und Typen, b) Präferenz für Rekursion gegenüber Schleifen und / oder c) reine Funktionen - dh solche Funktionen, die die gewünschte Semantik nicht beeinflussen des Programms, wenn es gespeichert ist ( daher existiert aufgrund der Auswirkungen der Betriebssemantik, z . B. der Speicherzuweisung, keine vollkommen reine funktionale Programmierung in einer allgemeinen Denotationssemantik ).

Die idempotente Eigenschaft einer reinen Funktion bedeutet, dass der Funktionsaufruf für ihre Variablen durch ihren Wert ersetzt werden kann, was bei den Argumenten einer imperativen Prozedur im Allgemeinen nicht der Fall ist. Reine Funktionen scheinen für die nicht zusammengesetzten Zustandsübergänge zwischen den Eingabe- und Ergebnistypen deklarativ zu sein.

Die Zusammensetzung reiner Funktionen behält jedoch keine solche Konsistenz bei, da es möglich ist, einen Nebeneffektprozess (globaler Zustand) in einer rein funktionalen Programmiersprache, z. B. Haskells IOMonad, zu modellieren, und darüber hinaus ist es völlig unmöglich, dies zu verhindern jede Turing komplett reine funktionale Programmiersprache.

Wie ich 2012 schrieb, was dem ähnlichen Konsens der Kommentare in Ihrem letzten Blog entspricht , ist diese deklarative Programmierung ein Versuch, die Vorstellung zu erfassen, dass die beabsichtigte Semantik niemals undurchsichtig ist. Beispiele für undurchsichtige Semantik sind die Abhängigkeit von der Ordnung, die Abhängigkeit vom Löschen der Semantik höherer Ebenen auf der Ebene der operativen Semantik (z. B. Casts sind keine Konvertierungen und reifizierte Generika begrenzen die Semantik höherer Ebenen ) und die Abhängigkeit von variablen Werten, die nicht überprüft werden können (bewiesen) richtig) durch die Programmiersprache.

Ich bin daher zu dem Schluss gekommen, dass nur nicht-Turing-vollständige Sprachen deklarativ sein können.

Ein eindeutiges und eindeutiges Merkmal einer deklarativen Sprache könnte daher sein, dass nachgewiesen werden kann, dass ihre Ausgabe einer Reihe von generativen Regeln entspricht. Beispielsweise kann für ein bestimmtes HTML-Programm (das Unterschiede in der Art und Weise, wie Interpreter voneinander abweichen) ignoriert wird, das nicht mit Skripten versehen ist (dh nicht vollständig ist), die Ausgabevariabilität aufzählbar sein. Kurz gesagt, ein HTML-Programm ist eine reine Funktion seiner Variabilität. Ebenso ist ein Tabellenkalkulationsprogramm eine reine Funktion seiner Eingabevariablen.

Es scheint mir also, dass deklarative Sprachen das Gegenteil einer unbegrenzten Rekursion sind , dh nach Gödels zweitem Unvollständigkeitssatz können selbstreferenzielle Sätze nicht bewiesen werden.

Lesie Lamport schrieb ein Märchen darüber, wie Euklid Gödels Unvollständigkeitssätze, die auf mathematische Beweise im Kontext der Programmiersprache angewendet wurden, um die Kongruenz zwischen Typen und Logik (Curry-Howard-Korrespondenz usw.) herum umgehen könnte.


4

Deklarative Programmierung ist "der Vorgang des Programmierens in Sprachen, die eher dem mentalen Modell des Entwicklers als dem Betriebsmodell der Maschine entsprechen".

Der Unterschied zwischen deklarativer und imperativer Programmierung wird durch das Problem der Analyse strukturierter Daten deutlich.

Ein zwingendes Programm würde gegenseitig rekursive Funktionen verwenden, um Eingaben zu verbrauchen und Daten zu generieren. Ein deklaratives Programm würde eine Grammatik ausdrücken, die die Struktur der Daten definiert, damit sie dann analysiert werden können.

Der Unterschied zwischen diesen beiden Ansätzen besteht darin, dass das deklarative Programm eine neue Sprache erstellt, die dem mentalen Modell des Problems enger zugeordnet ist als die Wirtssprache.


2

Es mag seltsam klingen, aber ich würde Excel (oder wirklich jede Tabelle) zur Liste der deklarativen Systeme hinzufügen. Ein gutes Beispiel dafür finden Sie hier .


1

Ich würde es erklären, da DP eine Möglichkeit ist, sich auszudrücken

  • Ein Zielausdruck , die Bedingungen für - wonach wir suchen. Gibt es einen, vielleicht oder viele?
  • Einige bekannte Fakten
  • Regeln, die die bekannten Fakten erweitern

... und wo es eine Deduktionsmaschine gibt, die normalerweise mit einem Vereinigungsalgorithmus arbeitet , um die Ziele zu finden.


-1

Soweit ich das beurteilen kann, wurde es verwendet, um Programmiersysteme wie Prolog zu beschreiben, weil es bei Prolog (angeblich) darum geht, Dinge abstrakt zu deklarieren.

Es bedeutet zunehmend sehr wenig, da es die oben von den Benutzern angegebene Definition hat. Es sollte klar sein, dass es eine Kluft zwischen der deklarativen Programmierung von Haskell und der deklarativen Programmierung von HTML gibt.


1
Es gibt keine "Kluft zwischen der deklarativen Programmierung von Haskell und der deklarativen Programmierung von HTML", da das Stammattribut der deklarativen Programmierung die Unveränderlichkeit gespeicherter Werte ist.
Shelby Moore III

Wie dem auch sei, es gibt einen fairen Unterschied zwischen einer domänenspezifischen Sprache, die selbst in ihren impliziten Berechnungen eingeschränkt ist, und einem vollständig programmierenden System.
Marcin

Einverstanden. Die Vollständigkeit der Turing ist orthogonal zur Unveränderlichkeit gespeicherter Werte. Wir sollten also nicht mit dem Attribut deklarativ vs. imperativ in Konflikt geraten. Vielen Dank, dass Sie über eines der Attribute (Turing-Vollständigkeit) nachgedacht haben, die diese "Kluft" verursachen können.
Shelby Moore III

Die Vollständigkeit des Drehens erfordert nur eine unbegrenzte Rekursion . Die Unveränderlichkeit gespeicherter Werte schließt eine unbegrenzte Rekursion nicht aus. Sie sind also orthogonale Attribute.
Shelby Moore III

-2

Einige andere Beispiele für deklarative Programmierung:

  • ASP.Net-Markup für die Datenbindung. Es heißt nur "Füllen Sie dieses Raster mit dieser Quelle" und überlässt es dem System, wie dies geschieht.
  • Linq-Ausdrücke

Deklarative Programmierung ist hilfreich, weil sie dazu beitragen kann, Ihr mentales Codemodell * zu vereinfachen , und weil sie möglicherweise skalierbarer ist.

Angenommen, Sie haben eine Funktion, die mit jedem Element in einem Array oder einer Liste etwas bewirkt. Herkömmlicher Code würde folgendermaßen aussehen:

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

Keine große Sache da. Was aber, wenn Sie die deklarativere Syntax verwenden und stattdessen DoSomething () als Aktion definieren? Dann können Sie es so sagen:

MyList.ForEach(DoSometing);

Dies ist natürlich prägnanter. Aber ich bin sicher, Sie haben mehr Bedenken, als nur hier und da zwei Codezeilen zu speichern. Leistung zum Beispiel. Die alte Art, die Verarbeitung musste nacheinander erfolgen. Was wäre, wenn Sie mit der .ForEach () -Methode signalisieren könnten, dass die Verarbeitung automatisch parallel ausgeführt werden kann? Jetzt haben Sie Ihren Code plötzlich auf sehr sichere Weise multithreaded gemacht und nur eine Codezeile geändert. Tatsächlich gibt es eine Erweiterung für .Net, mit der Sie genau das tun können.

  • Wenn Sie diesem Link folgen, gelangen Sie zu einem Blog-Beitrag eines Freundes von mir. Der ganze Beitrag ist etwas lang, aber Sie können bis zur Überschrift "Das Problem" scrollen und ihn dort problemlos abholen. *

1
Sie beschreiben die funktionale Programmierung, nicht die deklarative Programmierung . Deklarative Programmierung hat das Attribut, dass gespeicherte Werte nicht mutiert werden .
Shelby Moore III

Deklarative Programmierung kann gespeicherte Werte mutieren ... Sie müssen lediglich angeben (deklarieren), was Sie mutieren möchten, anstatt genau zu bestimmen, wie Sie es mutieren möchten. Was macht Ihrer Meinung nach eine SQL INSERT- oder UPDATE-Anweisung in SQL noch?
Joel Coehoorn

Sie verpassen den Punkt, dass unbeabsichtigte Nebenwirkungen die Beziehung zwischen dem, was Sie deklariert haben, und dem tatsächlichen Verhalten des Programms zerstören können, wenn Ihre Funktionen nicht rein sind. Ich habe dies in einer neuen Antwort ausführlicher erklärt .
Shelby Moore III

-3

Dies hängt davon ab, wie Sie die Antwort auf den Text senden. Insgesamt können Sie das Programm in einer bestimmten Ansicht betrachten, aber es hängt davon ab, aus welchem ​​Blickwinkel Sie das Problem betrachten. Ich werde Sie mit dem Programm beginnen: Dim Bus, Auto, Zeit, Höhe als Integr

Auch hier kommt es darauf an, was das Problem insgesamt ist. Möglicherweise müssen Sie es aufgrund des Programms kürzen. Hoffe das hilft und brauche das Feedback wenn es nicht geht. Danke.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.