2014-01-21 5 views
5

Diese Frage zu dem Material in Kapitel 3 des Buches bezieht sich: Programming in Prolog, Clocksin und Mellish, Ed 5Struktur (Differenz Listen) Prolog

In Seite 72 dieses Buches, ein Programm mit Differenzliste ist angezeigt:

partsOf(X,P):- partsacc(X,P,Hole) , Hole=[]. 

partsacc(X,[X|Hole],Hole):-basicpart(X). 
partsacc(X,P,Hole):- assembly(X,Subparts), partsacclist(Subparts, P, Hole). 

partsacclist([],Hole,Hole). 
partsacclist([P|T], Total, Hole):- partsacc(P,Total,Hole1), partsacclist(T,Hole1,Hole). 

In vielen Online-Tutorials, die das folgende Format zu verwenden "-" verwendet wird, zum Beispiel ::

append([ A , B , C | R1 ] – R1 , [ D , E | R2 ] – R2 , R3) 

Meine Fragen sind:

  1. Was ist der Unterschied zwischen diesen beiden Darstellungen (mit - und es nicht verwenden)

  2. In welchen Situationen ist es am besten jeden von ihnen zu benutzen?

Dank

+0

Vielen Dank für Ihre hilfreiche Kommentare. – user17302

Antwort

6

Auf jeden Fall: Verwenden Sie nicht (-)/2 oder (\)/2 oder einen anderen Operator, um "Differenzlisten" darzustellen. Der Grund dafür ist, dass Sie oft ein Prädikat mit einem Listenargument und einem internen Prädikat haben, das eine Differenzenliste verwendet. Wenn beide die gleiche Arität und wahrscheinlich auch den gleichen Namen haben, werden die Dinge verwirrend werden. Schlimmer noch, es könnte für "einige Fälle" funktionieren. Dieser Operator verursacht auch einige Kosten, die Sie mit zwei separaten Argumenten vermeiden können.

Versuchen Sie, eine saubere Namenskonvention einzuhalten.Das ist S0, S1 ... S. Auf diese Weise werden die Argumente, die die Differenzliste darstellen, leicht sichtbar. Um besser zu unterstreichen, dass diese Argumente zusammengehören, verwenden manche Leute kein Leerzeichen nach dem Trennkomma, während sie es für andere Argumente verwenden. Also:

p(L+R, S0,S) :- 
    p(L, S0,S1), 
    p(R, S1,S). 

Ferner hat die (-)/2 eine andere Bedeutung in Prolog. Es wird verwendet, um ein Paar Key-Value, wie in keysort/2 darzustellen.

Jedes Prolog-Buch, das ich kenne, einen Operator für Differenzlisten vorschlagen kommt aus den 1980er Jahren.

+0

@Will: Es gibt [authentische Antworten] (https://www.quora.com/profile/Alan-Kay-11), jetzt! – false

+0

interessant, danke. –

6

in Prolog Meine Erfahrung ist begrenzt, aber es scheint, dass ältere Texte sind in der Regel entweder das - oder ein anderes Zeichen (zum Beispiel \) zu bezeichnen, die Liste und den Schwanz zu verwenden. Neuere Prolog-Code verwendet immer zwei Argumente (wie in Ihrem ersten Beispiel). Beispielsweise verwenden alle integrierten und Bibliothekselemente in SWI-Prolog konsistent zwei separate Argumente.

In der Theorie gibt es keinen Unterschied, welchen Stil Sie bevorzugen. Ich schätze, es tut nicht weh, in deinem eigenen Code konsistent zu sein.

In der Praxis besteht der Unterschied darin, dass anstelle eines zusammengesetzten Terms, der zwei Listen in einem einzigen Argument enthält, zwei Argumente vorhanden sind, was eine effizientere Darstellung sein sollte.

EDIT

Stellen Sie sicher, auch durch @False die Antwort zu lesen.

6

Ich stimme dem zu, was Boris (+1) bezüglich der verschiedenen Darstellungen sagte. Darüber hinaus ist dies meines Erachtens eindeutig ein Fall, in dem Sie DCGs verwenden sollten, anstatt Listenunterschiede explizit zu kodieren. Betrachten Sie zum Beispiel die folgende Version des Codes:

parts(X) --> { basicpart(X) }, [X]. 
parts(X) --> { assembly(X, Parts) }, assembly_(Parts). 

assembly_([])  --> []. 
assembly_([X|Xs]) --> parts(X), assembly_(Xs). 

Verbrauch, nach der Definition assembly/2 und basicpart/1 genau wie in Ihrem Beispiel:

?- phrase(parts(X), Ls).

Die DCG hat eine klare deklarative und einfache Interpretation lesen und benötigt weniger Argumente.