| Logischer Ablauf | Exkurse |
|---|---|
|
|
| Beispieldatenbanken | |
SQL, eine Programmiersprache der 4. Generation, wurde speziell zum Erstellen, Verwalten und Manipulieren von Datenbanken erschaffen. Im Folgenden möchte ich zeigen, dass sich viele Funktionalitäten von SQL auch in Prolog, einer Programmiersprache der 5. Generation, realisieren lassen. Dabei beginnen wir bei einfachen SQL-Anweisungen und arbeiten uns zu komplizierteren Abfragen und Aggregatfunktionen vor.
Es geht also konkret darum, eine Datenbank Programmierung in Prolog vorzunehmen und die SQL-Anweisungen und -abfragen in dieser Programmiersprache umzusetzen.
Dabei geht es vor allem darum, möglichst viele verschiedene Lösungsansätze und -tricks aufzuzeigen, sodass man mit den erlernten Mitteln später selber arbeiten, variieren und neu kombinieren kann.
Es soll eine Datenbank für ein Handy-Adressbuch mit Informationen zu den Kontakten erstellt werden:
| Name | Telefonnummer | Geburtstag | Geburtsmonat | Geburtsjahr |
|---|---|---|---|---|
| Meier | 01712350393 | 21 | 01 | 1988 |
| Wolf | 029185930292 | 01 | 05 | 1985 |
| Engel | 021394210239 | 14 | 09 | 1988 |
| Muse | 03924019510 | 19 | 02 | 1997 |
Dazu wird jeder Datensatz (jede Zeile) als Fakt in Prolog abgelegt, wobei ein Argument für ein Datenfeld/Spalte steht:
%% person(Name, Telefonnummer, Geburtstag, Geburtsmonat, Geburtsjahr).
person('Meier', 01712350393,21,01,1988).
person('Wolf', 029185930292,01,02,1985).
person('Engel', 021394210239,14,09,1988).
person('Muse', 03924019510,19,02,1997).
Die Daten Geburtstag, Geburtsmonat und Geburtsjahr lassen sich noch schachteln. Das vereinfacht später das Arbeiten mit der Wissenbasis und schafft Übersichtlichkeit:
%% person(Name, Telefonnummer, Geburstag(Geburtstag, Geburtsmonat, Geburtsjahr)).
person('Meier', 01712350393, gebu(21,01,1988)).
person('Wolf', 029185930292, gebu(01,02,1985)).
person('Engel', 021394210239, gebu(14,09,1988)).
person('Muse', 03924019510, gebu(19,02,1997)).
Projektion ist das Auswählen bestimmter Datenfelder (Spalten/Attribute) zur Anzeige. Zu Beginn wollen wir alle gespeicherten Kontakte mit Namen und Telefonnummer ausgeben lassen. In SQL wäre das:
SELECT Name, Telefonnummer
FROM Kontakte
;
Selbe Anfrage in Prolog:
?- person(Name,Tel, _).
Hier nutzen wir anonyme Variablen (_). Damit kennzeichnen wir die Datenfelder, die wir nicht ausgeben wollen. Hier zeigt sich bereits ein Vorteil der Verschachtelung, da wir die gesamten Geburtsdaten mit nur einer Variablen ansprechen können.
Die Anfrage liefert somit:
Name = 'Meier',
Tel = 1712350393 ;
Name = 'Wolf',
Tel = 29185930292 ;
Name = 'Engel',
Tel = 21394210239 ;
Name = 'Muse',
Tel = 3924019510
Bei der Selektion geht es um die Auswahl von Datensätzen, die einer bestimmten Bedingung genügen. So wollen wir alle Datensätze jener Kontakte ausgegeben haben, die im Jahr 1988 geboren sind.
SQL:
SELECT *
FROM Kontakte
WHERE Geburtsjahr = 1988
;
Prolog:
?- person(Name,Tel, gebu(Geburtstag,Geburtsmonat,1988)).
%% oder
?- person(Name,Tel, gebu(Geburtstag,Geburtsmonat,X)), X = 1988.
liefert:
Name = 'Meier',oder:
Name = 'Meier',Wie auch in SQL lassen sich in Prolog Projektion und Selektion verknüpfen.
UND-Verknüpfungen werden in Prolog mit einem Komma zwischen den Einzelfragen gekennzeichnet. Hierfür wollen wir alle Kontakte ausgeben, die vor dem Jahre 1990 im Monat Sempember geboren sind.
SELECT Name, Telefonnummer, Geburtstag, Geburtsmonat, Geburtsjahr
FROM Kontakte
WHERE Geburtsjahr < 1990
AND Geburtsmonat = 09
;
?- person(Name,Tel, gebu(Geburtstag,09,X)), X < 1990.
liefert:
Name = 'Engel',
Tel = 21394210239,
Geburtstag = 14,
X = 1988 ;
Bei diesem Beispiel haben wir zum ersten Mal mit Vergleichsoperatoren gearbeitet. Weitere sind:
nach [1].
ODER-Verknüpfungen werden in Prolog mit einem Semikolon zwischen den Einzelfragen gekennzeichnet. Nun wollen wir alle Kontakte ausgeben, die entweder im Jahr 1988 oder im Jahr 1997 geboren sind.
SELECT Name, Telefonnummer, Geburtstag, Geburtsmonat, Geburtsjahr
FROM Kontakte
WHERE Geburtsjahr = 1988
OR Geburtsjahr = 1997
;
?- person(Name,Tel, gebu(Geburtstag,Geburtsmonat,X)), (X = 1988; X=1997).
%% oder
?- person(Name,Tel, gebu(Geburtstag,Geburtsmonat,1988)); person(Name,Tel, gebu(Geburtstag,Geburtsmonat,1997)).
Zur unserer Datenbank bzw. Wissensbasis in Prolog fügen wir noch Fakten über die Monate hinzu:
%% monat(Monat,Monatsname).
monat(01, 'Januar').
monat(02, 'Februar').
monat(03, 'März').
monat(04, 'April').
monat(05, 'Mai').
monat(06, 'Juni').
monat(07, 'Juli').
monat(08, 'Augst').
monat(09, 'September').
monat(10, 'Oktober').
monat(11, 'November').
monat(12, 'Dezember').
Tabellen können verknüpft werden, sofern sie ein gemeinsames Attribut (i. d. R. das Schlüsselattribut) besitzen. Datensätze die bei diesem Attribut den gleichen Wert aufweisen, werden in einer neuen Tabelle ausgegeben.
Jetzt wollen wir beide Tabellen verbinden, das gemeinsame Attribut/Schlüssel ist der Monat. Wichtig ist das dieser Schlüssel in beiden Teilanfragen mit der gleichen Variablen belegt ist und nicht anonymisiert (_) wird.
?- person(Name,_, gebu(_,Geburtsmonat,_)), monat(Geburtsmonat,Monatsname).
liefert:
Name = 'Meier',Name = 'Wolf',
Geburtsmonat = 5,
Monatsname = 'Mai' ;
Name = 'Engel',
Geburtsmonat = 9,
Monatsname = 'September' ;
Name = 'Muse',
Geburtsmonat = 2,
Monatsname = 'Februar'
Also:
| Name | Geburtsmonat | Monatsname |
|---|---|---|
| Meier | 1 | Januar |
| Wolf | 5 | Mai |
| Engel | 9 | September |
| Muse | 2 | Februar |
Nach dem Konsultieren einer Wissensbasis sind alle Fakten im Zwischenspeicher von Prolog geladen und können dann nicht mehr verändert werden. Erst erneutes Konsultieren lädt die Wissensbasis erneut. Um trotzdem Veränderungen durchzuführen müssen wir unsere Datenbasis als dynamisch definieren. Das geschieht mit dem Befehl :- dynamic funktor/stelligkeit:
:- dynamic person/3.
person('Meier', 01712350393, gebu(21,01,1988)).
person('Wolf', 029185930292, gebu(01,02,1985)).
person('Engel', 021394210239, gebu(14,09,1988)).
person('Muse', 03924019510, gebu(19,02,1997)).
Mit dem Befehl listing(funktor/stelligkeit) lassen sich die aktuellen Fakten im Zwischenspeicher ausgeben.
?- listing(person/3).
gibt Folgendes aus:
- dynamic person/3.
person('Meier', 1712350393, gebu(21, 1, 1988)).
person('Wolf', 29185930292, gebu(1, 5, 1985)).
person('Engel', 21394210239, gebu(14, 9, 1988)).
person('Muse', 3924019510, gebu(19, 2, 1997)).
Zu einer dynamischen Datenbasis können nun Fakten hinzugefügt und gelöscht werden. Dazu stehen diverse Befehle zur Verfügung:
| Befehl | Beschreibung |
|---|---|
| asserta(fakt). | Fügt einen neuen Fakt am Anfang des Stapels ein. |
| assertz(fakt). | Fügt einen neuen Fakt am Ende des Stapels ein. |
| retract(fakt). | Löscht Fakt. |
| retractall(fakt). | Löscht alle Fakten des Funktors |
| Befehl | Ausgabe bei ?- listing(person/3). |
|---|---|
| asserta( person('Fischer',09012394012,gebu(01,01,1992))). | person('Fischer', 9012394012, gebu(1, 1, 1992)). person('Meier', 1712350393, gebu(21, 1, 1988)). person('Wolf', 29185930292, gebu(1, 5, 1985)). person('Engel', 21394210239, gebu(14, 9, 1988)). person('Muse', 3924019510, gebu(19, 2, 1997)). |
| assertz( person('Fischer',09012394012,gebu(01,01,1992))). | person('Meier', 1712350393, gebu(21, 1, 1988)). person('Wolf', 29185930292, gebu(1, 5, 1985)). person('Engel', 21394210239, gebu(14, 9, 1988)). person('Muse', 3924019510, gebu(19, 2, 1997)). person('Fischer', 9012394012, gebu(1, 1, 1992)). |
| retract( person('Wolf', 29185930292, gebu(1, 5, 1985))). | person('Meier', 1712350393, gebu(21, 1, 1988)). person('Engel', 21394210239, gebu(14, 9, 1988)). person('Muse', 3924019510, gebu(19, 2, 1997)). |
| retractall(person(_,_,_)). |
Eleganter geht das mit der Definition einer Regel zum Einfügen und Löschen, die wir in die Prolog-Datenbasis schreiben:
einfuegen(Name, Tel, GebuTag, GebuMonat, GebuJahr):-
assertz(person(Name, Tel,gebu(GebuTag, GebuMonat, GebuJahr))).
Der SQL-UPDATE-Befehl wird mittels Löschen und neuem Einfügen in Prolog implementiert.
Nun beginnen wir mit den kniffligeren Dingen. Da wir immer komplexere Aufgaben an Prolog stellen, ist es von Vorteil, Anfragen als Regeln in unsere Datenbasis zu schreiben und diese dann aufzurufen (Wissen um die Lösungssuche in Prolog samt Backtracking und Unifikation ist zum Verständnis hilfreich).
Wir wollen die Namen der Kontakte mit dazugehöriger Telefonnummer auf dem Bildschirm ausgegeben. Dazu nutzen wir die Befehle write/1 und nl (new line, erzeugt eine neue Ziele).
abfrage1:-
person(Name,Tel,_),
write(Name), write(' hat die telefonnummer '),write(Tel),nl,
fail.
?- abfrage1.
liefert:
Meier hat die telefonnummer 1712350393Wichtig dabei ist das fail. Dadurch wird Prolog gezwungen nach weiteren Kontakten zu suchen, bis es alle Fakten in der Datenbasis durchgegangen hat.
Natürlich lässt sich diese Abfrage auch ohne write und fail realisieren: etwas uneleganter geht es mit der Regel:
abfrage1(Name,Telefonnummer):- person(Name,Telefonnummer,_).
Für Weiteres benötigen wir eine Reihe von neuen Befehlen, die in Prolog standardmäßig implementiert sind.
Es sollen alle Namen unserer Kontaktdatenbank alphabetisch sortiert ausgegeben werden. Wir wollen unsere Ergebnisse auf dem Bildschirm ausgeben.
SELECT Name
FROM Kontakte
ORDER BY Name
;
abfrage2:-
findall(Name,
person(Name,_,_),
Liste),
sort(Liste,SListe),
write(SListe).
ergibt:
['Engel', 'Meier', 'Muse', 'Wolf']Die Kür: Nun sollen alle Kontakte mit allen dazugehörigen Informationen sortiert nach dem Geburtsjahr ausgegeben werden. Und zwar ohne Listen bei der Ausgabe (Wissen um Rekursion und Listen (Kopf, Rest) nötig und Kenntnis vom Cut und Backtracking hilfreich).
SELECT *
FROM Kontakte
ORDER BY Geburtsjahr
;
abfrage3:-
findall([Jahr,person(Name,Tel,geburtstag_am(Tag,Monat,Jahr))],
person(Name,Tel,gebu(Tag,Monat,Jahr)),
Liste),
sort(Liste,SListe),
streichen(SListe,SSListe),
ausgabe(SSListe),!.
ausgabe([K]):- write(K),nl.
ausgabe([K|Rs]):- write(K),nl,ausgabe(Rs).
streichen([],[]).
streichen([[_,B]|Rs],[B|Qs]):- streichen(Rs,Qs).
liefert:
person(Wolf, 29185930292, geburtstag_am(1, 5, 1985))Zur Erklärung: Um zu Sortieren nutzen wir einen Trick: Wir schreiben vor jedes Listenelement noch einmal mit Kommata getrennt das Jahr, sodass findall/3 am Ende folgende Liste ausgibt:
Liste = [
[1988, person('Meier', 1712350393, geburtstag_am(21, 1, 1988))],
[1985, person('Wolf', 29185930292, geburtstag_am(1, 5, 1985))],
[1988, person('Engel', 21394210239, geburtstag_am(14, 9, 1988))],
[1997, person('Muse', 3924019510, geburtstag_am(19, 2, 1997))]
]
Nun sortiert sort/2 jedes Listenelement, wobei allein nach dem ersten Zeichen - dem Jahr - sortiert wird. Nun sorgt unsere selbst definierte rekursive Regel streichen/2 dafür, dass das Jahr am Anfang jedes Listenelements gelöscht wird. Anschließend nutzen wir die Regel ausgabe/1, um jedes Listenelement einzeln in eine extra Zeile auszugeben. Der grüne Cut ! unterdrückt unnötiges Backtracking und damit praktisch das Fragen von Prolog nach "More?"; ist aber für die Lösung nicht nötig.
Eines der ersten Dinge, die man in SQL lernt, sind Abfragen wie: Zeige alle Namen an, die mit "M" beginnen oder die Zeichenfolge "ei" im Namen tragen.
SELECT Name
FROM Kontakte
WHERE
Name LIKE "M*"
OR Name LIKE "*ei*"
;
Oder: Zeige alle Namen, die genau 5 Zeichen lang sind und mit "l" enden.
SELECT Name
FROM Kontakte
WHERE
Name LIKE "????l"
;
Dabei steht der Joker * für beliebig viele Buchstaben bzw. Zeichen und der Platzhalter ? für genau ein Zeichen. Um solche Anfragen in Prolog zu realisieren, benötigen wir den mächtigen Befehl sub_string/5:
Nun wissen wir alles, um auch solche SQL-Abfragen in Prolog implementieren:
abfrage4(Name):-
person(Name,_,_),
sub_string(Name,0,1,_,'M').
liefert:
Name = 'Meier' ;
Name = 'Muse'
oder mit Ausgabe:
abfrage5:-
write('mit m beginnen:'),nl,
(
person(Name,_,_),
sub_string(Name,0,1,_,'M').
write(Name),nl,
fail
).
liefert:
mit m beginnen:
Meier
Muse
Und jetzt alle Namen, die genau 5 Zeichen lang sind und mit "l" enden:
abfrage6:-
write('namen, die 5 zeichen lang sind und mit "l" enden:'),nl,
(
person(Name,_,_),
sub_string(Name,_,1,0,'l'),
sub_string(Name,_,5,_,_),
write(Name),nl,
fail
).
ergibt:
namen, die 5 zeichen lang sind und mit "l" enden:
Engel
Für die Demonstration von Aggregatfunktionen (Anzahl/count(), Summe/sum(), Minimum/min(), Maximum/max(), Durschnitt/avg() etc.) benötigen wir eine neue Datenbasis. Wir wählen die Datenbank eines Online-Kaufhauses, in dem sämtliche Bestellungen erfasst werden:
%%bestellung(Kunde,ArtikelNr,Anzahl,Datum(Monat,Tag,Jahr)).
bestellung('Meier',1001,2,datum(8,2,2008)).
bestellung('Engel',1012,1,datum(8,8,2008)).
bestellung('Meier',1021,1,datum(8,12,2008)).
bestellung('Fischer',1001,1,datum(9,11,2008)).
bestellung('Meier',1055,3,datum(10,22,2008)).
bestellung('Will',1001,2,datum(10,26,2008)).
bestellung('Fischer',1002,4,datum(11,02,2008)).
bestellung('Muse',1009,10,datum(11,11,2008)).
Die Kür#2: Wir möchten folgende Abfrage in Prolog implementieren: Die Anzahl der Bestellungen zu jedem Kunden.
SELECT Kunde, count(ArtikelNr) AS AnzahlDerBestellungen
FROM Bestellungen
GROUP BY Kunde
;
abfrage7:-
findall(Kunde,
bestellung(Kunde,_,_,_),
KList),
list_to_set(KList,SKList),
zaehle(SKList,KListA),
ausgabe(KListA),!.
zaehle([],[]).
zaehle([K|Rs],Qs):-
findall(K,
bestellung(K,_,_,_),
AList),
length(AList, Anzahl),
zaehle(Rs,Ws),
Qs = [[K-hat-Anzahl-bestellung(en)]|Ws].
ausgabe([K]):- write(K),nl.
ausgabe([K|Rs]):- write(K),nl,ausgabe(Rs).
Der Aufruf von abfrage7/0 liefert:
[Meier-hat-3-bestellung(en)]Es werden alle vorhandenen - auch mehrmals vorkommenden - Kunden der bestellung-Fakten in eine Liste geschrieben:
KListe = [Meier, Engel, Meier, Fischer, Meier, Will, Fischer, Muse]
In dieser wird dann mittels des Systemprädikats list_to_set/2 alle Duplikate gelöscht:
SKListe = [Meier, Engel, Fischer, Will, Muse]
Die selbstdefinierte rekursive Regel zaehle/2 sucht nun zu jedem Kunden die Anzahl der Bestellungen. So hat die AListe bei K = Meier den Inhalt [Meier,Meier,Meier], da für Meier 3 Bestellungen in der Datenbasis existieren. Das Systemprädikat length/2 zählt die Listenelemente dieser Liste und gibt diese als Variable Anzahl aus. Die Rekursion setzt ein, diesmal jedoch ohne den eben bearbeiteten Listenkopf. Das ganze geschieht so lange, wie Elemente in der Ausgangsliste sind. Anschließend wird im Rekursionsaufstieg jeder Kunde mit seiner Anzahl an Bestellungen nacheinander in die Ergebnisliste Qs geschrieben. Die Ausgabe erfolgt wieder mit unserer Regel ausgabe/2, die wir schon aus "Suchen und Sortieren - Abfrage 3" kennen. Ebenso bekannt ist das optionale Setzen des grünen Cuts !, der unnötiges Backtracking von Prolog verhindert.
Die Umsetzung der SQL-Aggregatfunktion sum() in Prolog gestaltet sich analog zur Anzahlimplementation, nur dass hier nicht length/2, sondern unsere selbst definierte Regel summe/2 zum Einsatz kommt.
Auch hier gestaltet sich die Prolog-Implementation der SQL-Befehle min() bzw. max() analog zur Anzahl, nur dass wir statt length/2 unsere Regeln min/2 bzw. max/2 nutzen.
Trotzdem möchte ich diese Definition noch einmal an einem anderem - einfacheren ;-) - Beispiel demonstrieren. Dazu folgende Datenbank: Die Zeugnisnoten von Schülern werden in einer Prolog Wissensbasis als Fakten abgelegt:
%%zeugnis(Schueler, Note1, Note2, Note3, Note4).
zeugnis('Flink',2,3,2,5).
zeugnis('Pfiffig',1,1,2,1).
zeugnis('Faul',3,4,3,5).
zeugnis('Albern',3,2,3,3).
zeugnis('Klug',1,1,1,1).
Gesucht ist die beste Note von jedem Schüler.
beste_note:-
zeugnis(Name,N1,N2,N3,N4),
NotenL = [N1,N2,N3,N4], &&Listenbildung!
min(NotenL,Beste),
write('die beste note von '),write(Name),write(' ist '),write(Beste), nl,
fail.
min(Liste,Min):-
msort(Liste,SListe),
erstes_element(SListe,Min).
erstes_element([X|_],X).
der Aufruf von beste_note/0 liefert:
die beste note von Flink ist 2Beim Vergleich der Abfragen, die sich auf unsere Bestellungs- und unserer Zeugnisdatenbank beziehen, zeigen sich grundlegende Unterschiede hinsichtlich der Lösungsansätze:
| Exkurs: Komplexität der Listenbildung | |
|---|---|
| Der Umfang der Implementation von Aggregatfunktionen und ähnlich geartete Aufgaben in Prolog hängt von der Art der Wissenbasis hinsichtlich der Fakten bzw. von der Komplexität der Listenbildung ab: Sind die nötigen Informationen auf verschiedene Fakten verteilt, so ist eine Listenbildung mit findall/2 nötig (siehe Anzahl beim Bestellungsbeispiel). Sind die Informationen jedoch in einem Fakt zu finden, ist nur eine einfache Listenbildung mit List = [Element1, Element2, ...] zu realisieren (siehe Zeugnisbeispiel): | |
| Beispielfakten | notwendige Listenbildung mit: |
bestellung('Meier',1001,2,datum(8,2,2008)).Hier soll eine Liste aus den Anzahlwerten der bestellten Waren einer jeden Bestellung erstellt werden. Z. B. zur späteren Ermittlung der höchsten Bestellmenge. Für weiterführende Informationen siehe Anzahl-Abfrage. |
findall(Anzahl, bestellung(_,_,Anzahl,_), Liste). |
zeugnis('Flink',2,3,2,5).Hier wollen wir alle Noten in eine Liste zusammenfassen, um beispielsweise später die beste, die schlechteste oder den Durchschnitt zu berechnen. |
Liste = [Note1, Note2, Note3, Note4].
|
Was zur Realisierung der avg()-Funktion in Prolog nötig ist, können wir bereits: Summe der Liste (summe/2) bestimmen und durch die Länge (length/2) teilen.
Für unser Zeugnisbeispiel wäre die Lösung:
durchschnitt:-
zeugnis(Name,N1,N2,N3,N4),
NotenL = [N1,N2,N3,N4],
summe(NotenL,Summe),
length(NotenL,Anzahl),
Durchschnitt is Summe/Anzahl,
write('der durchschnitt von '),write(Name),write(' ist '),write(Durchschnitt), nl,
fail.
summe([],0).
summe([X|Rs], N):-
summe(Rs,N1),
N is N1 + X.
durchschnitt/0 liefert:
der durchschnitt von Flink ist 3Hier ein Zusammenfassung aller Prolog-Befehle und -Prädikate (Systemprädikate und/oder Listenprädikate), die wir genutzt haben:
| Prädikat | Kurze Beschreibung | Anwendung/ Beispiel: | |
|---|---|---|---|
| Dynamische Datenbankverwaltung | :- dynamic funktor/stelligkeit. | definiert die entsprechenden Fakten als dynamisch. | mehr... |
| listing(funktor/stelligkeit) | gibt alle Fakten des Zwischenspeichers aus | mehr... | |
| asserta(fakt). | Fügt einen neuen Fakt am Anfang des Stapels ein | mehr... | |
| assertz(fakt). | Fügt einen neuen Fakt am Ende des Stapels ein | mehr... | |
| retract(fakt). | Löscht Fakt | mehr... | |
| retractall(fakt). | Löscht alle Fakten des Funktors. | mehr... | |
| Ausgabe | write(+X) | gibt X auf dem Bildschirm aus | mehr... |
| nl | erzeugt eine neue Zeile auf dem Bildschirm | mehr... | |
| Backtrackingmanipulation | fail | erzwingt Backtracking | mehr... |
| ! | verhindert Backtracking (Cut) | mehr... | |
| Suchen | findall(?Template, +Generator, ?Liste) | sucht alle Lösungen des Generator-Ziels und gibt sie in Form des Templates als Liste aus. | mehr... |
| Sortieren | sort(+L,-SL) | sortiert die Liste L; löscht Duplikate | mehr... |
| msort(+L,-SL) | sortiert die Liste L; behält Duplikate | mehr... | |
| reverse(+L,-RL) | dreht die Liste L um | mehr... | |
| Stringanalyse und Stringmanipulation | sub_string(+String, ?Davor, ?Länge, ?Danach, ?Sub) | Kopiert aus String den Ausschnitt Sub mit Informationen zu der Position und Länge des Ausschnitts. Liefert Strings. | mehr... |
| sub_atom(+Atom, ?Davor, ?Länge, ?Danach, ?Sub) | Kopiert aus Atom den Ausschnitt Sub mit Informationen zu der Position und Länge des Ausschnitts. Liefert Atome. | mehr... | |
| Listenbefehle | list_to_set(+L,-L2) | Löscht Duplikate der Liste L und gibt sie als L2 aus. | mehr... |
| length(+L,-Anzahl) | Gibt die Anzahl der Listenelemente der Liste L aus. | mehr... | |
| last(+L,-E) | Gibt das letzte Listenelement der Liste L als E aus. | mehr... | |
| member(+X,+L) | Prüft ob X ein Listenelement der Liste L ist. | mehr... | |
| append(+L1,+L2,-GL) | Hängt Liste L1 an die Liste L2 an und gibt sie als GL aus. | / | |
| delete(+L,+X,-GL) | Löscht das Element X aus der Liste L und gibt sie als GL aus. | / | |
| Sonstiges | not(bedingung) | Negierung. Ist erfüllt, wenn die Bedingung fehlschlägt. | mehr... |
Kommentare
Es sind keine Kommentare vorhanden