我想寫一個謂詞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
我想寫一個謂詞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
我敢肯定,一個內置的操作存在這樣做的這......但基本上你只是試圖對通過謂詞的列表成員進行findall。試試這個過濾器的實現。運行第二個參數,直到所有結果都用盡,並將所有M值都收集到Result中。要做到這一點
filter(List,PredName,Result) :-
findall(M, (member(M, List), call(PredName,M)), Result).
一種方法是使用遞歸和「呼叫」謂詞
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).
如果您正在使用SWI-Prolog的,你可以使用exclude
謂詞從"apply" library
請注意,使用'(= ..)/ 2'像你一樣,限制'PredName'到一個原子。這意味着Goal必須是arity 1的謂詞。使用'call/2'可以更靈活:現在可以使用任何合適的謂詞,arity> = 1。這通常非常有用。另請參閱@尼克麥克斯的答案。 – false
@false你能舉一個例子來澄清你說的嗎? –
一個簡單的例子:考慮你想過濾掉所有元素'E',使得'E \ == 3'。使用'(= ..)/ 2',你必須定義一個新的謂詞'noteqeq3(E): - E \ == 3.「,但用'call/2'可以交出'\ ==(3)直接。 – false