2016-02-25 9 views

Antwort

5

Ihre Frage ist sehr legitim, +1.

Der Grund für diese scheinbar willkürliche Wahl ist, dass (is)/2 ein vergleichsweise niedrige Ebene Prädikat ist und funktioniert nur in sehr speziellen Fällen, die nur prozedural verstanden werden können, deklarativ nicht. Daher ist (is)/2 für Anfänger sehr schwer zu verstehen und sollte besser vermieden werden, da es viele relationale Eigenschaften zerstört, die wir bei der Verwendung von Prolog genießen möchten.

Die deklarative Lösung ist Constraints, wo Sie genau das tun können, was Sie sagen. Bei Beziehungen über ganze Zahlen ersetzen Sie einfach (is)/2 durch (#=)/2, um die relationalen Eigenschaften zu genießen, die Sie intuitiv erwarten.

Zum Beispiel mit GNU   Prolog:

 
count([], 0). 
count([_|Ls], N) :- 
     count(Ls, X), 
     X #= N - 1, 
     N #> 0. 

In anderen Systemen wie SICStus Prolog und SWI, die Sie aktuell benötigen noch library(clpfd) für diesen Einsatz. Darüber hinaus empfehle ich einen deklarativen Namen für diese Beziehung, klar zu machen, welches Argument, was bedeutet:

 
:- use_module(library(clpfd)). 

list_length([], 0). 
list_length([_|Ls], N) :- 
     list_length(Ls, X), 
     X #= N - 1, 
     N #> 0. 

Beispielabfragen:

 
?- list_length([_,_,_], N). 
N = 3. 

?- list_length(Ls, 2). 
Ls = [_G602, _G605] . 

Ich lasse die Verbesserung die Beendigung Eigenschaften dieses Prädikats als einfaches Übung.

+1

Danke für Ihre detaillierte Antwort Matte! Am Anfang Ihrer Antwort haben Sie gesagt, dass (es)/2 in sehr speziellen Fällen funktioniert. Weißt du wo ich mehr Informationen dazu finden könnte? Auf der Website von SWI-Prolog heißt es, dass es mit einem ungebundenen linken Operanden verwendet werden sollte, aber es ist mir nicht sehr klar (In meinen Lektionen steht: "Der rechte Ausdruck sollte zum Zeitpunkt des Anrufs vollständig instanziiert sein. "). – azekirel555

+1

Kein Wunder, dass Ihnen das nicht ganz klar ist: Gerade als Anfänger haben Sie fast keine Chance zu verstehen, wie '(is)/2' verwendet werden muss. Zur späteren Referenz informiere ich Sie nur, dass die rechte Seite vollständig instanziiert sein muss und dass ihre linke Seite eine Variable * sein soll, wenn das Ziel aufgerufen wird * (ugh!). Aber warum sollte man sich überhaupt mit dieser Logik * hacken * anstatt mit der Logik * programmieren * beschäftigen? Verwenden Sie '(# =)/2' und' (#>)/2' durchgehend und genießen Sie die relationale Natur dieser Prädikate, die in ** allen ** Richtungen verwendbar sind. Ich habe zu meiner Antwort weitere Erklärungen dazu hinzugefügt. – mat

+0

Ihre letzte Bemerkung ist vielleicht etwas zu indirekt ... – false

Verwandte Themen