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
If you are using SWI-Prolog you could use the exclude
predicate from the "apply" library
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).
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).