Zuerst wollen wir mal sehen, was passiert, wenn Sie eine Verbindung abfragen (der Operator) zuerst:
?- airport(nyc, _), write('found!').
found!
true.
?- airport(abc, _), write('found!').
false.
Das bedeutet, isAirport(abc)
nicht direkt nach dem Versuch airport(abc,_)
ohne Der Rest Ihres Prädikats wird ausgewertet. In vielen Fällen können Sie also ohne explizite erhalten, indem if-then-else-Konstrukt und nur etwas von der Form schreiben
predicate(X) :-
first_condition(X),
second_condition(X).
und es wird nur gelingen, wenn beide Bedingungen für X
erfüllt sind.
Falls Sie wirklich eine Benutzerschnittstelle erstellen möchten, ist dies ein wenig komplizierter, weil I/O von Natur aus nicht logisch ist, insbesondere wenn es sich um Backtracking handelt. Wir rufen normalerweise ein Programm auf, das sich so verhält, wie wir es von einer logischen Formel erwarten würden, und wenn es nicht-logische Konstrukte wie I/O enthält oder der cut-Operator !
heißt unrein.
Leider sind das if-then-else Konstrukt (->
und ;
) und Negation (\+
) über Schnitt implementiert und daher auch unrein. Zum Glück sind die meisten der Zeit, die Menschen ein bedingter wollen, ein reines disjunction genügt:
case(1,a).
case(2,b).
Wir haben eine automatische von der Ausführungsmechanismus von Prolog Verzweigung:
?- case(X,Y).
X = 1,
Y = a ;
X = 2,
Y = b.
Aber manchmal wirklich wollen wir etwas das benötigt die unreinen Konstrukte, wie Benutzereingaben. Dann ist der einfachste Weg, um die schönen logischen Eigenschaften unseres Programms zu halten, ist die Aufgabe, in reine und unreinen zu trennen:
main :-
uinput(Data),
pure_predicate(Data, Result),
write(Result).
Nachdem wir alle unreinen Teile getan haben, Data
ist vereinigt mit den Benutzerdaten, die wir wollten.Schauen wir uns die Implementierung von uinput/1
einen Blick:
uinput(data(Airport,D-M-Y)) :-
format('~nAirport? '),
read(Airport),
(ground(Airport), airport(Airport, _))
->
(
format('~nDay? '),
read(D),
format('~nMonth? '),
read(M),
format('~nYear? '),
read(Y),
(ground(D-M-Y), isDate(D-M-Y))
->
true
;
throw(failure('unknown date'))
)
;
throw(failure('unknown airport'))
.
Wir nacheinander Begriffe aus der Eingabe gelesen und eine Ausnahme auslösen, wenn wir es nicht verarbeiten kann. Damit das if-then-else-Konstrukt funktioniert, müssen wir besonders vorsichtig sein. Wenn wir die zwei Abfragen vergleichen:
?- between(1,3,X), write(X).
1
X = 1 ;
2
X = 2 ;
3
X = 3.
und
?- between(1,3,X) -> write(X); false.
1
X = 1.
können Sie sehen, dass die if-then-else verliert Lösungen. Dies bedeutet, dass wir sicherstellen müssen, dass unser Zustand deterministisch ist. Es ist schon eine gute Idee, nach einem Benutzereingabebegriff zu suchen, der geerdet werden soll, denn ohne Variablen gibt es nur einen Lösungsbegriff. Dennoch kann ein Aufruf an eines der Datenprädikate airport/1
und isDate/1
den gleichen Begriff mehrmals generieren oder gar nicht beenden. In diesem speziellen Fall müssen wir nur noch dafür sorgen, dass jeder Flughafen einen eindeutigen Namen für die Verknüpfung hat, können wir auch Termine ohne Wiederholung erzeugen:
airport(nyc, 'New York City').
airport(wdc, 'Washington DC').
isDate(X-Y-Z) :-
between(1,31,X),
between(1,12,Y),
between(1970,2100,Z).
Ein weiterer Trick, bei der Umsetzung von uinput
ist, dass wir nur mit true
gelingen, wenn Wir haben alles validiert. Der einzige Effekt von ist jetzt, dass Data
mit dem initialisiert wird, was auch immer der Benutzer eingegeben hat.
Wenn wir eine Dummy-Implementierung der tatsächlichen Umsetzung geben, können wir versuchen bereits die Umsetzung oursevles:
pure_predicate(_Data, Result) :-
% here goes the actual stuff
Result='we have found something awesome'.
Auf der Aufforderung wir das reine Prädikat ohne Probleme verwenden können:
?- pure_predicate(someinputdata,Y).
Y = 'we have computed something awesome'.
On Andererseits können wir auch das vollständige Prädikat wie folgt verwenden:
?- main(_).
Airport? wdc.
Day? |: 1.
Month? |: 2.
Year? |: 2000.
we have found something awesome
true.
Da wir lesen, müssen wir Prolog Terme eingeben und mit einem Punkt .
beenden, aber alles hat wie erwartet funktioniert.
Fall In der Benutzereingabe fehlschlägt, erhalten wir:
?- main(_).
Airport? bla(X).
ERROR: Unhandled exception: failure('unknown airport')
Bitte beachten Sie, dass wir nur durch diese Schwierigkeiten gingen zum Scheitern verurteilt tatsächlich früh und eine Benutzermeldung in diesem Fall geben. Für die eigentliche Berechnung ist dies völlig unnötig.
Wenn Sie "airport (abc, _)" abfragen und "abc" ist kein Flughafen in der Datenbank, wird es einfach fehlschlagen. Sie müssen die Variable im zweiten Argument nicht überprüfen. In der Tat, 'airport (Air, T)' wird fehlschlagen und Ihre 'var (T)' wird nicht einmal aufgerufen, wenn 'Air' kein Flughafen ist. Prolog hat einige grundlegende Verhaltensweisen, die Sie lernen müssen, bevor Sie versuchen, ein vollständiges Programm zu schreiben. Sie sollten ein gutes Lehrbuch und/oder Tutorial durchgehen. – lurker