Prolog filter a list of all elements for which a c

2019-07-08 03:58发布

问题:

I am trying to write a predicate filter(List, PredName, Result) that filters a List of all its elements for which the goal PredName fails and subsequently returns the Result list. The predicate PredName/1 should be defined when calling the procedure filter/3 and could for example be:

test(N) :- N >= 0

A query could then be made like following:

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

回答1:

If you are using SWI-Prolog you could use the exclude predicate from the "apply" library



回答2:

I'm sure a builtin operation exists to do this... but essentially you are just trying to do a findall on the member of the list that pass the predicate. Try this implementation of filter out. The second arg to findall is run until all results are exhausted and all values of M are collected into Result.

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


回答3:

One way to do that is using recursion and 'call' predicate

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

other way to that is instead of call you can use =.. (univ) operator.

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

=.. operator takes a list that contains predicate name and its arguments and returns newly created term. for example:

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