2011-07-13 43 views
3

我想寫一個謂詞filter(List, PredName, Result),它過濾所有元素的List,其目標PredName失敗並隨後返回Result列表。謂詞PredName/1應該調用過程filter/3時被定義並可以例如是:序言過濾器自定義目標失敗的所有元素的列表

test(N) :- N >= 0 

查詢然後可以做出類似以下內容:

?- filter([-6,7,-1,0], test, L) 
L = [7, 0]; 
no 

回答

1

我敢肯定,一個內置的操作存在這樣做的這......但基本上你只是試圖對通過謂詞的列表成員進行findall。試試這個過濾器的實現。運行第二個參數,直到所有結果都用盡,並將所有M值都收集到Result中。要做到這一點

filter(List,PredName,Result) :- 
    findall(M, (member(M, List), call(PredName,M)), Result). 
-1

一種方法是使用遞歸和「呼叫」謂詞

filter([],_,[]). 
filter([H|T], PredName, [H|S]) :- call(PredName,H),filter(T,PredName,S),!. 
filter([H|T], PredName, S) :- filter(T,PredName,S). 

其他方式是不是叫你可以使用=..(大學)運算符。

filter([],_,[]). 
filter2([H|T], PredName, [H|S]) :- Goal =.. [PredName,H],Goal,filter(T,PredName,S),!. 
filter([H|T], PredName, S) :- filter(T,PredName,S). 

=..運營商採用包含謂詞的名字和它的參數和返回新創建的項的列表。例如:

?-X =.. [f,a,b]. 
X = f(a, b). 
+0

請注意,使用'(= ..)/ 2'像你一樣,限制'PredName'到一個原子。這意味着Goal必須是arity 1的謂詞。使用'call/2'可以更靈活:現在可以使用任何合適的謂詞,arity> = 1。這通常非常有用。另請參閱@尼克麥克斯的答案。 – false

+0

@false你能舉一個例子來澄清你說的嗎? –

+0

一個簡單的例子:考慮你想過濾掉所有元素'E',使得'E \ == 3'。使用'(= ..)/ 2',你必須定義一個新的謂詞'noteqeq3(E): - E \ == 3.「,但用'call/2'可以交出'\ ==(3)直接。 – false

3

如果您正在使用SWI-Prolog的,你可以使用exclude謂詞從"apply" library

相關問題