2016-07-17 101 views
4

此代碼按預期工作:bagof只給一個項目,雖然多個項目適合

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

,但類似的電話,一個我真正想要的,並不:

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

;給我更多的答案 - 但我想[a,b,c,d]。我的修復程序是什麼?

回答

2

您需要存在性資格,你是不感興趣的,而不是使用匿名變量的參數:

?- 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]. 

這是必要的,因爲bagof/3(和setof/3)將返回解決方案包(集)的每個自由變量的實例化(即目標中不在模板中的變量)。在可替代的,你可以使用findall/3謂詞(忽略自由變量):

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

但要注意的findall/3時,有沒有解決辦法返回一個空列表,而bagof/3(和setof/3)時,有沒有解決方案失效。

另一種選擇,以避免在通話存在性限定的變量的一長串bagof/3setof/3是用一個單一的條款,其頭只列出你感興趣的參數引入一個輔助謂詞,例如:

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

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

真的很不錯的「伎倆」馴服bagof/3涉及語法! – CapelliC

+0

我也這麼認爲!有關findall/3 v。bagof/3的更多信息,請訪問:http://www.swi-prolog.org/pldoc/man?predicate=findall/3。謝謝! –

3

bagof/3_不直接聚在一起。 setof/3也是如此。

於是要麼放棄所有這些匿名變量名和它們聲明爲一個局部變量,使用輔助謂詞,或使用library(lambda)

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

該代碼片段在我的解釋器中不起作用 - 這是SWI-PROLOG,如果這有所作爲。 ? –

+3

您需要安裝[相應的包](http://www.swi-prolog.org/pack/list?p=lambda)。 – false

1

保羅貢獻庫(yall),自動加載在SWI-Prolog的。 Yall(又一個Lambda圖書館)輕鬆解決您的問題:

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