Пролог фильтрует список всех элементов, для которых не удается выполнить пользовательскую цель - PullRequest
3 голосов
/ 13 июля 2011

Я пытаюсь написать предикат 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

Ответы [ 3 ]

3 голосов
/ 13 июля 2011

Если вы используете SWI-Prolog, вы можете использовать предикат exclude из библиотеки «apply»

1 голос
/ 13 июля 2011

Я уверен, что для этого существует встроенная операция ... но, по сути, вы просто пытаетесь выполнить поиск для члена списка, передающего предикат.Попробуйте эту реализацию фильтра.Второй аргумент для findall выполняется до тех пор, пока все результаты не будут исчерпаны и все значения M не собраны в Result.

filter(List,PredName,Result) :-
  findall(M, ( member(M, List), call(PredName,M)), Result).
0 голосов
/ 13 июля 2011

Один из способов сделать это - использовать рекурсию и предикат 'call'

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

Другой способ - вместо вызова вы можете использовать оператор =.. (univ).

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).
...