2016-07-17 4 views
4

Dieser Code funktioniert wie erwartet:bagof gibt nur ein Element, wenn mehrere Artikel passen

?- bagof(R,member(r(R),[r(a),r(b),r(c),r(d)]),Rs). 
Rs = [a, b, c, d]. 

aber ein ähnlicher Anruf, den ich wirklich will, nicht:

?- bagof(R,member(r(_,R),[r(_,a), r(_,b), r(_,c), r(_,d)]),Rs). 
Rs = [a] 

; gibt mir mehr Antworten - aber ich möchte [a,b,c,d]. Was ist mein Problem?

Antwort

2

Sie müssen existentiell die Argumente qualifizieren, die Sie in anstelle von anonymen Variablen nicht interessiert sind:

?- bagof(R,A^A1^A2^A3^A4^member(r(A,R),[r(A1,a), r(A2,b), r(A3,c), r(A4,d)]),Rs). 
Rs = [a, b, c, d]. 

Dies ist notwendig, da bagof/3 (und setof/3) für einen Beutel (Set) von Lösungen zurück jede Instantiierung der freien Variablen (dh der Variablen im Ziel, die nicht in der Vorlage enthalten sind). In Alternative können Sie das findall/3 Prädikat verwenden (die freie Variablen ignoriert):

?- findall(R,member(r(A,R),[r(A1,a), r(A2,b), r(A3,c), r(A4,d)]),Rs). 
Rs = [a, b, c, d]. 

Aber beachten Sie, dass findall/3 gibt eine leere Liste, wenn es keine Lösungen gibt, während bagof/3 (und setof/3) fehlschlagen, wenn es keine Lösungen gibt.

Eine weitere Alternative eine lange Liste von existentiell qualifizierten Variablen in Anrufen bagof/3 und setof/3 zu vermeiden, ist ein Hilfs Prädikat mit einem einzigen Satz, dessen Kopf nur listet die Argumente, die Sie interessiert sind, einzuführen. Zum Beispiel:

r(R) :- 
    member(r(_,R),[r(_,a), r(_,b), r(_,c), r(_,d)]). 

?- bagof(R, r(R), Rs). 
Rs = [a, b, c, d]. 
+1

Wirklich nett 'Trick' zähmen bagof/3 beteiligt Syntax! – CapelliC

+0

Ich denke auch so! Mehr über findall/3 v. Bagof/3 hier: http://www.swi-prolog.org/pldoc/man?predicate=findall/3. Vielen Dank! –

3

bagof/3 und _ nicht direkt zusammenlaufen. Gleiches gilt für setof/3.

Also entweder alle diejenigen anonymen Variablen einen Namen geben und sie als lokale Variable deklarieren, ein Hilfs Prädikat verwenden oder library(lambda) verwenden:

?- bagof(R,R+\member(r(_,R),[r(_,a), r(_,b), r(_,c), r(_,d)]),Rs). 
Rs = [a,b,c,d]. 
+0

Dieses Code-Snippet funktioniert nicht in meinem Interpreter - das ist SWI-PROLOG, wenn das einen Unterschied macht. ? –

+3

Sie müssen [das entsprechende Paket] installieren (http://www.swi-prolog.org/pack/list?p=lambda). – false

1

Paulo beigetragen Bibliothek (yall), automatisch geladen in SWI-Prolog. Yall (Yet Another Lambda Library) löst Ihr Problem einfach:

?- bagof(R, {R}/member(r(_,R),[r(_,a), r(_,b), r(_,c), r(_,d)]),Rs). 
Rs = [a, b, c, d]. 
Verwandte Themen