2010-06-08 14 views

Antwort

16

Elegante Systeme bieten false/0 als deklaratives Synonym für den Imperativ fail/0. Ein Beispiel, wo es sinnvoll ist, wenn Sie manuell für Nebenwirkungen Rückzieher zwingen wollen, wie:

?- between(1,3,N), format("line ~w\n", [N]), false. 
line 1 
line 2 
line 3 

Statt false/0, können Sie auch jedes Ziel verwenden, die zum Beispiel etwas kürzer ausfällt:

?- between(1,3,N), format("line ~w\n", [N]), 0=1. 
line 1 
line 2 
line 3 

So ist false/0 nicht unbedingt erforderlich, aber ziemlich nett.

EDIT: Ich manchmal Anfänger sehen, wer zum Beispiel „meine Beziehung für die leere Liste nicht gilt“ angeben mag, und fügen Sie dann:

my_relation([]) :- false.

zu ihrem Code. Dies ist nicht erforderlich, und nicht ein gutes Beispiel für die Verwendung von false/0, außer zum Beispiel in Fehler-Slices, die programmgesteuert generiert werden. Stattdessen konzentrieren Sie sich auf die Dinge, die halten über Ihre Beziehung. In diesem Fall lassen Sie die gesamte Klausel aus, und die Beziehung definieren nur für Listen, die nicht leer sind, dh sie haben mindestens ein Element:

my_relation([L|Ls]) :- etc.

oder, wenn Sie beschreiben andere Begriffe zusätzlich auch verwenden, um eine Einschränkung wie Listen:

my_relation(T) :- dif(T, []), etc.

nur entweder Given (oder auch beide) dieser beiden Klauseln, die Abfrage ?- my_relation([]). automatisch fehlschlagen. Es ist nicht notwendig, eine zusätzliche Klausel einzuführen, die zu diesem Zweck niemals erfolgreich ist.

+0

s/elegant/elegant und konform/ – false

2

Ein Fall (von Constraint Logic Programming using Eclipse genommen) ist eine Implementierung von nicht/1: (!)

:- op(900, fy, not). 
not Q :- Q, !, fail. 
not _ . 

Wenn Q erfolgreich ist, der Schnitt bewirkt, dass die zweite Klausel nicht verworfen werden, und das gewährleistet, fail einen negativen Ergebnis. Wenn Q fehlschlägt, wird die zweite Nicht-Klausel zuerst ausgelöst.

1

Eine weitere Verwendung für nicht bestanden ist Rückzieher durch Alternativen zu erzwingen, wenn Prädikate mit Nebenwirkungen mit:

writeall(X) :- member(A,X), write(A), fail. 
writeall(_). 

Einige Leute nicht diesen besonders guten Programmierstil obwohl betrachten könnten. :)

+0

Hoppla, sieht aus wie Mat Beat mich dazu. – hdan

7

Explizites Versagen.fail wird oft in Verbindung mit Schnitt: ... !, fail. verwendet, um Fehler zu erzwingen.

Für alle Konstrukt. Explizite Verwendung von fail/false zum Aufzählen über Backtracking ist eine sehr fehleranfällige Aktivität.Betrachten wir einen Fall:

... (generator(X), action(X), fail ; true), ... 

Die Idee ist also zu „tun“ Aktion für alle X. Aber was passiert, wenn action(X) fehlschlägt? Dieses Konstrukt wird einfach mit dem nächsten Kandidaten — fortgesetzt, als ob nichts passiert wäre. Auf diese Weise können bestimmte Fehler sehr lange unentdeckt bleiben.

Für solche Fälle ist es besser zu verwenden \+ (generator(X), \+ action(X)), die fehlschlägt, sollte action(X) für einige X fehlschlagen. Einige Systeme bieten dies als eine eingebaute forall/2. Persönlich bevorzuge ich \+ in diesem Fall, weil die \+ ein bisschen klarer ist, dass das Konstrukt keine Bindung verlässt.

Fehler-Slice. Für diagnostische Zwecke ist es oft sinnvoll, die Programme false in Ihre Programme einzufügen. Weitere Informationen finden Sie unter .

Verwandte Themen