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

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

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

Я уверен, что для этого существует встроенная операция... но, по сути, вы просто пытаетесь выполнить поиск для члена списка, передающего предикат. Попробуйте эту реализацию фильтра. Второй аргумент 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).

Другой путь к этому вместо вызова вы можете использовать =.. (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).
Другие вопросы по тегам