- Prolog baut Programme aus einer einzigen Clause und einem term-zentrierten Datenmodell auf und kann so auch mit kleiner Syntax berechenbare Relationen ausdrücken
- Der deklarative Ansatz beschreibt eher, was gilt, als die Ausführungsprozedur, sodass dieselbe Relation zum Berechnen, Generieren und Abfragen genutzt werden kann
- Reines Prolog basiert auf Horn clauses und Resolution; die Auswirkungen zusätzlicher Constraints und zusätzlicher Clauses auf die Lösungsmenge sind logisch vorhersagbar
- Das Programm selbst ist ein Prolog-Term, wodurch sich andere Programme leicht lesen, analysieren und transformieren lassen; durch Umschreiben zur Compile-Zeit lassen sich auch domänenspezifische Sprachen erstellen
- Dank Laufzeit-Dynamik und impliziter Mechanismen wie Suche, Unifikation und Constraint-Propagation wird Prolog breit eingesetzt, von Sprachverarbeitung über Datenbanken und Verifikation bis Optimierung
Eine kleine Sprache aus Clauses und Terms
- Alle Daten in Prolog werden als Prolog-Term dargestellt
- Das zentrale Sprachelement ist eine Clause; die Grundform ist
Head :- Body.
- Die Bedeutung lautet: Wenn Body gilt, gilt Head
- Der Infix-Operator
(:-)/2 stellt einen von rechts nach links gerichteten Pfeil ← dar
- Wenn Head immer gilt, kann
:- Body weggelassen werden
- Diese Struktur reicht aus, um ein erstes nützliches Prolog-Programm zu schreiben
- Alle bekannten Berechnungen lassen sich mit solchen Clauses beschreiben, daher ist Prolog eine Turing-vollständige Sprache
- Eine Turing machine kann implementiert werden, indem man die Relation vom aktuellen Zustand und dem Symbol unter dem Bandkopf zum nächsten Zustand als Clauses beschreibt
- Eine Beispielimplementierung findet sich in turing.pl
Deklaratives Programmieren und relationales Denken
- Prolog ist eine deklarative Sprache, die ausdrückt, was über die interessierenden Lösungen gilt, statt wie man sie findet
- Dieser Charakter ermöglicht knappe, klare und allgemeine Spezifikationen
- Die Relation zwischen einer Liste und ihrer Länge lässt sich so beschreiben
list_length([], 0).
list_length([_|Ls], N) :-
N #> 0,
N #= N0 + 1,
list_length(Ls, N0).
- In manchen Prolog-Systemen muss eine separate Bibliothek eingebunden werden, um deklarative Ganzzahlarithmetik zu verwenden
- Diese Definition lässt sich deklarativ wie folgt lesen
- Die Länge der leeren Liste
[] ist 0
- Wenn die Länge von
Ls N0 ist und N gleich N0 + 1 ist, dann ist die Länge von [_|Ls] N; diese Relation gilt nur, wenn N größer als 0 ist
- Dieselbe Relation kann in mehreren Modi verwendet werden
list_length("abc", L) gibt L = 3 zurück
list_length(Ls, 3) findet eine Listenform der Länge 3: Ls = [_A,_B,_C]
list_length(Ls, L) listet allgemeine Antworten auf, beginnend mit der leeren Liste bis hin zu Listen mit zunehmender Länge
- Prolog meldet normalerweise alle Antworten per Backtracking
length/2 ist im Entwurf von Prologue for Prolog enthalten und wird in fast allen Prolog-Implementierungen als eingebautes Prädikat mit derselben Bedeutung bereitgestellt
Prolog als Logikprogrammierung
- Zur Kategorie deklarativer Sprachen gehören funktionale Programmiersprachen und Sprachen der Logikprogrammierung
- Funktionen sind ein Spezialfall von Relationen; funktionale Programmierung kann als eingeschränkte Form der Logikprogrammierung betrachtet werden
- Prolog hat seine Wurzeln in der Logik
- Reine Prolog-Programme bestehen aus einer Menge von Horn clauses
- Die Ausführung kann als Spezialfall der Resolution betrachtet werden
- Dank der Verbindung zur formalen Logik lässt sich deklaratives Debugging auf Basis der logischen Eigenschaften eines Programms anwenden
- Fügt man Constraints hinzu, wird die Lösungsmenge höchstens kleiner
- Fügt man Clauses hinzu, wird die Lösungsmenge höchstens erweitert
- Diese Eigenschaft reiner Prolog-Programme nennt man Monotonie
- Ulrich Neumerkels GUPU system ist ein Anwendungsbeispiel für diese Idee
Homoikonische Eigenschaft: Programme wie Daten behandeln
- Prolog-Programme sind zugleich gültige Prolog-Terms
- Dank dieser Eigenschaft können Prolog-Programme andere Prolog-Programme leicht analysieren, transformieren und interpretieren
- Mit dem eingebauten Prädikat
read/1 lassen sich Prolog-Terms lesen, also auch Prolog-Clauses
- Prolog verfügt über einen leistungsfähigen Makro-Mechanismus, der Programme zur Compile-Zeit umschreibt
- Damit lassen sich domänenspezifische Sprachen implementieren, mit denen sich Aufgaben natürlicher lösen lassen
list_length(Ls,N) und N#>0 sehen in der Schreibweise unterschiedlich aus, werden aber durch Prologs Prefix-, Infix- und Postfix-Operatoren in besser lesbarer Form ausgedrückt
- Zum Beispiel kann der Prolog-Term
+(a,b) in Operatorschreibweise als a+b geschrieben werden
- Da die abstrakte Syntax einheitlich ist, können alle Prolog-Terms unabhängig von ihrer Schreibweise gelesen und verarbeitet werden
- Benutzerdefinierte Operatoren für bestimmte Zwecke können dynamisch definiert werden
Laufzeit-Dynamik und Erweiterbarkeit
- Prolog-Programme lassen sich zur Laufzeit leicht erzeugen, aufrufen und ändern
- Diese Eigenschaft erhöht die Ausdruckskraft und ermöglicht die Implementierung von Prädikaten höherer Ordnung, die andere Prädikate als Argumente erhalten
- Auch sehr dynamische Techniken wie adaptive parsing lassen sich implementieren
- Prolog eignet sich gut zum Schreiben von Programmen, die durch benutzerdefinierte Regeln anderer Programmierer oder normaler Nutzer erweitert werden
- Ein Interpreter für reines Prolog kann in zwei Zeilen Prolog-Code definiert werden
- Verwandte Inhalte behandelt A Couple of Meta-interpreters in Prolog
Vielfältige Einsatzbereiche und implizite Mechanismen
- Prologs relationaler Charakter macht Programme flexibel und allgemein
- Dieser Charakter spielt eine wichtige Rolle bei der Wissensrepräsentation in der Sprachverarbeitung und in Datenbanken
- Moderne Prolog-Systeme bieten die nötigen Funktionen von einfachen logic puzzles bis hin zu großen Anwendungen
- Prologs Vielseitigkeit und Stärke wurzeln in impliziten Mechanismen wie Suche, Unifikation, Argument-Indexierung und Constraint-Propagation
- Entwickler können diese Mechanismen nutzen und viele Aufgaben an die Prolog-Engine delegieren
1 Kommentare
Hacker-News-Kommentare
Diesem Gefühl stimme ich hier fast vollständig zu. Ich habe in drei KI-Kursen an der Uni Prolog verwendet, dabei fast ganz „AI: A Modern Approach“ und Prolog-Programmierung behandelt, und es war wirklich eine denkende-verrenkende Erfahrung.
Um wieder in Prolog-Art zu denken, brauchte ich immer ein Aufwärmen, und in diesem Semester schrieb ich sogar in anderen Sprachen furchtbar Prolog-artigen Spaghetti-Code. Der größte Nachteil damals war, dass die Interoperabilität mit anderem schwierig war: Man musste Prolog in die JVM einbetten, eine funktionsarme Implementierung verwenden oder sich auf C-Bindings stützen. Für bestimmte Aufgaben, insbesondere Constraint-Satisfaction-Probleme, ist es großartig, aber sobald Dinge wie Benutzeroberflächen oder Dateisystemzugriff dazukommen, passte es meiner Ansicht nach nicht mehr. Damals war auch SWI noch im Rückstand, und man verwendete proprietäre Lösungen wie Sicstus; als ich zuletzt nachgesehen habe, hatte SWI zu den proprietären Implementierungen aufgeschlossen, und heute würde ich wohl SWI wählen. Die Prolog-Prüfung war die furchteinflößendste an der Uni: drei Live-Coding-Aufgaben in 60 Minuten, gefolgt von einer mündlichen Prüfung. Aber ich verbrachte 40 Minuten mit der einfachen Aufgabe und löste die beiden übrigen in wenigen Minuten, sodass es gut ausging. In einem Folgekurs war die Aufgabe, Game-Playing-Agents zu implementieren und in einem Turnier gegeneinander antreten zu lassen, was Spaß machte; „The Art of Prolog“ und „The Craft of Prolog“ gehören bis heute zu den besten Programmierbüchern, die ich gelesen habe.
The Craft of Prolog ist ebenfalls hervorragend, aber es ist sehr stark auf alte Prolog-Systemprogrammierung spezialisiert, sodass einige Kapitel heute veraltet sind. Viele Ideen aus Prolog leben in Answer-Set-Programming und Datalog weiter, und Datalog eignet sich hervorragend zum Bau moderner statischer Analysatoren: https://arxiv.org/abs/2012.10086
Plötzlich frage ich mich, wie Chatbots mit Prolog umgehen. Haben sie genug davon gesehen? Können sie auf diese Weise schlussfolgern?
Prolog ist großartig, und allein wegen der Erfahrung eines ungewohnten Programmierparadigmas lohnt es sich, es zu lernen. Viele Konzepte werden auf völlig andere Weise ausgedrückt, und wenn einem das Paradigma erst einmal einleuchtet, wird es eher deutlich einfacher.
In Prolog manipuliert man zum Beispiel normalerweise keine Collections direkt, sondern liefert Informationen darüber, was die Elemente einer Collection sind, und lässt die Implementierung es herausfinden. Auch das Zeichnen eines Abhängigkeitsbaums ist mit drei Regeln möglich: was die Entitäten sind, wie man die Beziehung zwischen Entität X und Y bestimmt und wie man sie darstellt. Weil es aber schwierig ist, ist es schwer, andere davon zu überzeugen, es zu lernen oder zu verwenden, und ich habe noch keinen Weg gefunden, es sauber in andere Apps zu integrieren. Ich weiß, dass FFI eine Option ist, bin aber nicht überzeugt, dass das produktionsreif ist. In den letzten Monaten habe ich nach eher „produktionsnahen“ Prolog-Alternativen gesucht, aber LispWorks oder Franz Allegro CL waren zu teuer und nicht integrationsfreundlich genug. Mich würden wirklich Beispiele interessieren, in denen Prolog gut in moderne Software integriert wurde. Da XPCE auf dem Mac nicht läuft, suche ich auch nach einer GUI-Lösung. Als Online-Notebook ist Swish ebenfalls einen Blick wert: https://swish.swi-prolog.org
Soweit ich gehört habe, ist das inzwischen entfernt, also kein „modernes“ Beispiel, aber es ist ein wirklich schönes Beispiel für den Einsatz von Prolog. Der Weg von https://news.ycombinator.com/item?id=36821871 zu https://web.archive.org/web/20030218034509/http://www.resear... lohnt sich sehr zu lesen. Verwandter Link: https://news.ycombinator.com/item?id=14046420
Beides funktionierte ziemlich gut, aber die Anwendungsfälle waren begrenzt. Meine Erfahrung mit Prolog an der Uni war interessant, aber wenn ein Problem nicht im Kern Prolog-förmig ist, würde ich es nicht verwenden wollen. Sobald man anfängt, etwas auch nur etwas Komplexeres zu implementieren, lecken die Abstraktionen überall, und es fühlt sich stärker danach an, mit dem Backtracking-Algorithmus zu kämpfen, als die Vorteile der Sprache zu nutzen.
Racklog bettet Prolog-artige logische Programmierung in Racket ein, und „Einbettung“ bedeutet hier, dass man Racket nicht verliert. Man kann Prolog-artige Codefragmente und normalen Racket-Code nebeneinander schreiben. Es enthält die meisten Prolog-Funktionen, einschließlich Meta-Logik und Prädikaten zweiter Ordnung für „Mengen“, und lässt nur die Funktionen weg, die sich als Racket-Teilausdrücke einfacher und effizienter erledigen lassen. https://docs.racket-lang.org/racklog/index.html Racket hat auch eine GUI und im Grunde fast alles, was man braucht.
CUE lässt sich viel leichter in bestehende Workflows einbauen und eignet sich daher gut, um die Vorteile logischer Programmierung praktisch nutzbar zu machen. https://cuelang.org | https://cuetorials.com
Über mehrere Jahre habe ich in C++ Software zur Supply-Chain-Optimierung entwickelt und dabei ILOGs Constraint-Propagation-Software verwendet, den Solver, der heute IBM gehört. Damals habe ich mir auch BinProlog angesehen; es hatte Bereichspropagation eingebaut, kompilierte zu nativem x86 und die FFI-Interoperabilität war ordentlich
Am Ende scheint es aber doch von SWI Prolog und der GNU-Toolchain verdrängt worden zu sein. GUI sollte man wohl als ein ganz anderes Spezialgebiet betrachten; wir nutzten unsere eigene C++-Canvas-Rendering-Engine und ein schreckliches integriertes 4GL-Entwicklungstool namens „4D“ bzw. „Fourth Dimension“. https://www.tomshw.it/data/images/2/0/4/3/infor-advanced-sch...
Mark Tarvers Sprache Shen enthält eine vollständige Implementierung von Prolog: https://shenlanguage.org/SD/Prolog.html
Es gibt auch das entsprechende Kapitel in The Book of Shen: https://shenlanguage.org/TBoS/tbos_359.html Tarver hat außerdem zwei Bücher über logische Programmierung geschrieben, jeweils mit begleitender Software. Logic, Proof and Computation: https://shenlanguage.org/lpc.html Programming the Logic Lab: https://shenlanguage.org/logiclab.html
Pattern Matching, optionale Typprüfung und das eingebaute Prolog sind beeindruckend. Wegen der diplomatischen Art des Schöpfers wurde er in gewisser Weise von der breiteren Community ausgeschlossen, aber er ist brillant, und die Verbreitung blieb nischig und am vorderen Rand. Wenn eine Organisation wie Mozilla dahintergestanden hätte, wäre es wohl deutlich massentauglicher gewesen. Die Vorträge von @deech sind inzwischen alt, aber immer noch hervorragend und relevant: https://www.youtube.com/watch?v=lMcRBdSdO_U, https://www.youtube.com/watch?v=BUJNyHAeAc8 Allerdings bin ich ein begeisterter APL/J/BQN-Fan, also entsprechend einordnen
Ich erinnere mich, dass ich vor etwa 25 Jahren in einem Studiengang für KI + Informatik Prolog gelernt habe. Im Modul zur Verarbeitung natürlicher Sprache haben wir es viel verwendet
Anfangs war es frustrierend und nervig, aber wenn man sich daran gewöhnt hatte, machte es überraschend viel Spaß; und weil es für Schleifen nur Rekursion gab, war es auch ein hervorragender Einstieg in Rekursion
An der Universität lernten wir Prolog überwiegend von Mathematikern, die fast nur solche Sprachen verwendeten, und für sie war Prolog eine sehr natürliche Denkweise. Für Studierende hingegen, die hauptsächlich prozedurale Sprachen gewohnt waren, war es verwirrend und frustrierend, und alle versuchten, Prolog wie eine andere Sprache zu schreiben, was schiefging. Erst im dritten oder vierten Kurs mit Prolog, nachdem ich die dahinterliegenden Algorithmen studiert hatte, verstand ich, wie man es richtig benutzt. Später half ich einem Bachelor-Studenten, der mit Prolog kämpfte; der Kern war, nicht zu versuchen, Prolog dazu zu bringen, sich wie die bekannten Sprachen zu verhalten, sondern die eigene Problemlösungsweise an die Prolog-Welt anzupassen. Nach einem recht langen Gespräch kam der echte Aha-Moment, und er schloss die Aufgabe sehr gut ab
Aber nachdem das neue Paradigma in meinem Kopf einmal eingerastet war, mochte ich es wirklich. Allein dieser Aha-Moment war die Teilnahme an dem Kurs wert
Andere Kommentare sprechen über Prolog im Allgemeinen, aber ich möchte sagen, dass The Power of Prolog eine ziemlich gute Tutorial-Serie ist
Auch die Videos sind sehenswert, und Markus hält das Interesse von Zuschauern und Lesern gut aufrecht
Dieses Video hat mir geholfen, Prolog als eine gegenwärtige und fortschrittliche Bewegung in der Programmierung zu begreifen
Prolog ist eine schöne Sprache. Ich habe damit Zehntausende Zeilen für mathematisches Schließen, regelbasiertes Schließen und Ähnliches geschrieben; für solche Bereiche passt es perfekt, und die Arbeit macht enorm viel Spaß
Für andere Arten von Anwendungen gibt es zwei Probleme. Erstens ist das Paradigma so anders, dass es sich schlecht mit Bibliotheken und anderen Sprachen verträgt. Zweitens ist es nahezu unmöglich, eine anständige GUI zu bauen, ebenfalls weil sie nicht zum Paradigma passt
Aus Prolog-Sicht sieht eine externe Schnittstelle normalerweise wie ein Prädikat aus, bei dem alle Argumente grundiert sind; von außen interagiert man mit Prolog wie mit einer SQL-Datenbank. Man sendet Abfragen, zerlegt Abfragen und fordert weitere Lösungen an oder treibt Backtracking an. Man kann sagen, dass diese Interaktion „nicht interessant“ ist, aber sie funktioniert so, weil die Bibliotheken die nützlichen Fähigkeiten von Prolog in der Praxis nicht ausnutzen. Wenn man will, kann man eine dickere Interoperabilitätsschicht bauen und mehrere Bibliotheksfunktionen zu einer einzigen Prädikatschnittstelle auf der Prolog-Seite bündeln, die dann je nach Instanziierungsmodus der Argumente bestimmte Subroutinen aufruft. Das unterscheidet sich aber nicht grundlegend davon, eine C-Bibliothek in einer objektorientierten Sprache wie Python verfügbar zu machen und dabei mehrere C-Funktionen als Property-Accessor oder Methoden einer Datenstruktur zu bündeln
Ich nutze Prolog aktiv für Datenanalyse. Am Anfang braucht es eine Phase, in der man sich dazu zwingt, möglichst alles in Prolog zu machen, um zu verstehen, wie man Fragen in symbolische Probleme übersetzt
Das liegt daran, dass Prolog wissenschaftliches Rechnen und String-Manipulation miserabel unterstützt. Hat man diese Hürde hinter sich, sind Prolog-Lösungen oft eleganter als die nächstbeste Alternative. Außerdem ist es ein logisches Paradigma, daher lohnt es sich, Zeit darin zu investieren, zu verstehen, wie Beweis durch Negation + Unifikation = Logikprogrammierung wird. Unter den Programmiersprachen, die ich gelernt habe, hat sie meinen Horizont mit Abstand am stärksten erweitert.
Standard-Prolog hat keine eingebauten regulären Ausdrücke, aber die verbreiteten Implementierungen stellen dafür normalerweise Bibliotheken bereit. Wenn ich viel String-Arbeit erledigen müsste und zwischen C und Prolog wählen müsste, würde ich definitiv Prolog nehmen. Bei Python und Prolog käme es auf die Aufgabe an.
Jedenfalls eine großartige Seite, und ich freue mich, dass dieses Thema wieder aufkommt.
Ich hatte zuvor schon einen Löser in Java geschrieben und versuchte, diesen Code nach Prolog zu übertragen, aber das funktionierte überhaupt nicht. Am Ende fing ich von vorn an und schrieb einfachen Prolog-Code, der prüft, ob ein Sudoku gültig ist, und merkte dann, dass man durch Ausführen dieser Prädikate das Sudoku auch lösen kann. So hatte ich den Löser in weniger als 10 Zeilen fertig. Das war ein echter Heureka-Moment; Prolog ist sehr mächtig, wird in der Praxis aber unfairerweise viel zu wenig genutzt. Zum Glück hatte ich Gelegenheit, mit Datalog und OWL zu arbeiten.