GUI Programmierung in Prolog

Es passiert immer wieder: Man stößt auf eine Programmiersprache die “irgendwie cool” ist, und mit der es Spaß macht, kleine Sachen zu schreiben. Spätestens nach ein paar ersten Gehversuchen möchte man dann aber mehr, am liebsten natürlich etwas Grafisches (oft gibt man es ungern zu, aber insgeheim wissen wir doch alle dass EyeCandy rockt). So ist mir mit Prolog ergangen.

Mittlerweile bin ich aber so weit, auch erste GUI-Erfahrungen zu haben. Damit es anderen vielleicht leichter fällt, werde ich hier eine kleine Einführung in GUI-Programmierung mit Prolog geben.

Zuerst einmal wäre es praktisch, wenn du ein wenig Erfahrung mit Prolog hättest. Dennoch funktionieren die folgenden Beispiele auch ohne weitergehende Kenntnisse in logischer Programmierung.

Getting things up and running

Im Folgenden arbeiten wir mit XPCE, Windows- und Mac-User laden sich ein Stable-Release herunter , unter Ubuntu landet alles was du benötigst mit einer Zeile auf deinem System

sudo aptitude install swi-prolog swi-prolog-xpce

Per Aufruf von “xpce” startest du die interaktive Prolog-Shell. Die folgenden Befehle kannst du einfach der Reihe nach in die Shell eingeben, Pro-Tipp ist das Anlegen einer .pl Datei die in der Shell geladen wird. Dazu aber erst im nächsten Beispiel.

Das erste Beispiel

new(@dialog, dialog('Hello World')).
new(@button,button('Moin!',message(@prolog,write_ln,'Hello World') ) ).
send(@dialog,append(@button)).
send(@dialog,open).

Ausprobieren. Klappt? Gut. Klappt nicht? Nicht gut, melde dich mal in den Kommentaren. Oder schau erstmal, dass du alles richtig abgetippt hast (Punkte am Ende jeder Zeile nicht vergessen!).

Was XPCE zusätzlich zur logischen Programmierung liefert, sind Objekte. Diese werden mit new() erzeugt, wobei sie einen von uns gewählten Namen bekommen (@dialog). Der zweite Parameter von new() enthält den Konstruktor-Aufruf, welcher weitere Parameter enthalten kann. Bei button(‘Moin!’,message(@prolog,write_ln,’Hello World’) zum Beispiel zuerst eine Beschriftung (“Moin!”), sowie ein XPCE-Codefragment, das bei Klicken des Buttons ausgeführt werden soll. In unserem Fall ist dies das Senden einer Nachricht an das @prolog-Objekt. Dieses Objekt ist vordefiniert, und erlaubt uns, aus XPCE wieder Prolog-Code aufrufen zu können. In usnerem Beispiel soll write_ln mit dem Parameter “Hello World” aufgerufen werden.

Was man wissen muss

Prolog ist eine Sprache, die das Paradigma der Logischen Programmierung verfolgt. Anders als in imperativen Sprachen wie Java, C, Php oder Konsorten schreibt man keine Anweisungen, sondern definiert Fakten und Regeln, über die der Interpreter dann Schlüsse ziehen kann. Hierdurch lassen sich mit wenig Aufwand komplexe logische Zusammenhänge beschreiben. Gerade in Bereichen wie der künstlichen Intelligenz oder regelbasierten Spielsystemen (wie Schach und andere Brettspiele) zeigen sich die Stärken von Prolog.

Die Kehrseite der Medaille ist, dass existierende Systembibliotheken (GUI wäre da nur ein Beispiel) imperativ und funktional arbeiten. Um solche Funktionalitäten zu nutzen muss man sich daher für einen Mittelweg entscheiden.

XPCE stellt dafür Objekte bereit, mit denen man in Prolog-Syntax kommunizieren kann. Flexibilität wie zum Beispiel Richtungsunabhängigkeit geht hierbei leider verloren. Dafür laufen mit XPCE entwickelte GUIs plattformunabhängig und mit wählbaren Look&Feels.

Die wichtigsten XPCE Befehle sind new() zum Erzeugen eines Objektes, send() zum Senden von Nachrichten an Objekte, get() zum Abfragen des Objektzustandes und free() zum Entfernen von Objekten.

Ein komplexeres Formular

Lege die folgende Datei an, nenne sie meinetwegen formular.pl

newgame:-
    new(D,dialog('New Game')),
    send_list(D,append,
    [
    new(Name,text_item('Player Name')),
    new(Race,menu(race,cycle)),
    new(NumberOfPlayers,int_item('Number of players',low:=1,high:=10)),
    new(Ok,button('OK'))
   ]),
   send_list(Race, append, [wizard,warrior,elb]),
   send(D,open).

In deiner XPCE-Shell lädst du das externe Skript über “consult(formular.pl).” oder über “[formular].” (ohne Dateiendung .pl!) und startest dein Programm über den Prädikatsaufruf “newgame.” Was hier jetzt neu sind, sind noch ein paar Formularelemente (text_item, menu, int_item) sowie das praktische send_list Prädikat, das ermöglicht, viele Argumente zu einer Liste zusammenzufassen wenn diese zum Beispiel an das gleiche Objekt gesendet werden sollen.

Lasst uns malen

Natürlich kann man mit XPCE auch Grafiken erstellen. Simple zweidimensionale Objekte wie Kreise und Rechtecke sind ebenso machbar wie Bezierkurven oder das Einbinden von Grafiken.

gfx:-
 new(P,picture('Bunte Formen')),
 new(Box,box(100,100)),
 new(Circle,circle(100)),
 send(Box,fill_pattern,orange),
 send(Circle,fill_pattern,red),
 send(P,display(Box,point(10,10))),
 send(P,display(Circle,point(150,10))),
 send(P,open).

Wo lerne ich mehr?

Zugegebenermaßen gewöhnungsbedürftig ist die XPCE-Dokumentation (auch erreichbar mit “manpce.” aus der interaktiven Shell). Besser zu lesen, zu verstehen und auch mit vielen Beispielen versehen ist der XPCE Userguide (PDF 2MB).

Mit den Möglichkeiten von XPCE stößt man aber auch schnell an die Grenzen, vergleichbar mit modernen GUI-Bibliotheken wie Qt und ähnlichen kann XPCE bei weitem nicht mithalten. Dennoch ist es toll, mit wenig Aufwand einfach Oberflächen für die eigenen Prolog-Programme erstellen zu können. Ich wünsche euch viel Spaß dabei!