2010-11-09 5 views
13

Also der univ-Operator. Ich verstehe es nicht genau.Prolog GNU - Univ Betreiber? Erklärung davon

Zum Beispiel dieses:

foo(PredList,[H|_]) :- bar(PredList,H). 
foo(PredList,[_|T]) :- foo(PredList,T),!. 

bar([H|_],Item) :- G =.. [H,Item],G. 
bar([_|T],Item) :- bar(T,Item). 

Was ist dies zu tun? Dies sieht aus, ob ein anderes Prädikat wahr ist. Ich verstehe nicht, was das ".." tut.

Wie würden Sie dies ohne den univ-Operator umschreiben?

+1

+1 für die Frage, wie man ohne univ. Übrigens gibt es die ISO-Prädikate funktor/3 und arg/3, die in einigen Fällen die Aufgabe erfüllen könnten und bevorzugt werden sollten, aber ich bin mir nicht sicher, ob sie immer verwendet werden können. – Kaarel

+0

@Kaarel, +1. Meine Antwort wurde aktualisiert. –

Antwort

14

Univ (=..) zerlegt einen Begriff in eine Liste von Bestandteilen oder konstruiert einen Begriff aus einer solchen Liste. Versuchen:

?- f(x,y) =.. L. 
L = [f, x, y]. 

?- f(x,y,z) =.. [f|Args]. 
Args = [x, y, z]. 

?- Term =.. [g,x,y]. 
Term = g(x, y). 

bar scheint mit foo Rückzieher über die Item s jedes Prädikat in PredList auf Item, zu nennen. (Unter Verwendung einer Variablen als ein Prädikat nicht tragbar ist, das call Prädikat bevorzugt werden sollte.)

bearbeiten: Kaarel richtig ist, kann univ durch functor/3 und arg/3 ersetzt werden, wie folgt:

bar([H|_],Item) :- 
    functor(Goal,H,1), % unifies Goal with H(_) 
    arg(1,Goal,Item), % unifies first argument of Goal with Item 
    call(Goal).   % use this for portability 
+3

Gute Antwort.Nur zur Verdeutlichung: Der univ-Operator vereinheitlicht den Begriff auf der linken Seite mit der Liste auf der rechten Seite, so dass der Kopf der Liste der Funktor ist und der letzte Teil der Liste die Argumente sind. –

+0

Hmm interessant. Vielen Dank! – Matt

+0

@larsmans: Sie zwingen "H", ein Atom zu sein. So verhindern Sie teilweise Anwendung! Siehe @Cookie Monster's Lösung. – false

2

die am besten geeignete Umschreiben meiner Meinung nach wäre:

bar([H|_], Item) :- call(H, Item). 

call/n sind noch nicht Teil des ISO Kernstandard, aber sie könnten becom e in naher Zukunft (*). Viele Prolog-Systeme unterstützen sie bereits.

Es gibt einen Grund, warum call/n sollten über einfache (=..)/2 und functor/3 + arg/3 Lösungen bevorzugt werden. Die call/n Lösung kann mit Verschlüssen (**) umgehen.

Mit dem einfachen (=..)/2 und functor/3 + arg/3 Lösung kann man bar/2 nur mit Atomen in der ersten Liste Argument aufrufen. Zum Beispiel:

p1(1). 
p2(2). 
?- bar([p1, p2], 1). 
Yes 
?- bar([p1, p2], 2). 
Yes 
?- bar([p1, p2], 3). 
No 

Mit Verschlüssen sind wir nicht auf Atome beschränkt, und wir könnten etwas Programmieraufwand sparen. Zum Beispiel können wir die folgenden direkt tun:

?- bar([=(1), =(2)], 1). 
Yes 
?- bar([=(1), =(2)], 2). 
Yes 
?- bar([=(1), =(2)], 3). 
No 

Mit freundlichen Grüßen

(*)
Draft Technical Corrigendum 2
http://www.complang.tuwien.ac.at/ulrich/iso-prolog/dtc2#call

(**)
Wer es call/n erfunden ?: Prädikate
http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/naish.html

+1

Über "Wer erfand es": Die tatsächliche erste schriftliche Quelle, die ich kenne, ist der _1984 Draft Proposed Standard für Prolog Evaluable Predicates_ von Richard O'Keefe, der erstmals 1984/07/25 öffentlich angekündigt wurde. Sie finden einen Vorläufer, der auf einige nicht vollständig spezifizierte Lambda-Typen beschränkt ist, aber ** eine teilweise Anwendung nicht zuläßt ** in Mycroft, O'Keefe _Ein polymorphes System für Prolog_, AI Journal, August 1984. – false

+1

Ich nehme an, das entspricht der Aussage "(1) Alan Mycroft und ich erfanden Call/N zusammen. Niemand sonst war beteiligt." von ROK in der zweiten Referenz gefunden? –

+0

Irgendwie. Aber nicht ganz. Es gibt andere Aussagen, die nahelegen, dass "call/N" in diesem Papier bereits erfunden wurde. – false