Простой Пролог удалить из списка

(Это не вопрос курсовой работы. Просто мое личное обучение.)

Я пытаюсь выполнить упражнение в Прологе, чтобы удалить элементы из списка. Вот мой код:

deleteall([],X,[]).
deleteall([H|T],X,Result) :- 
    H==X,
    deleteall(T,X,Result).
deleteall([H|T],X,[H|Result]) :- deleteall(T,X,Result).

Когда я проверяю его, я сначала получаю хороший ответ (т. Е. Со всеми удаленными X). Но затем при возврате мне предлагаются все другие варианты списка с некоторыми или ни с одним удаленным экземпляром X.

Почему это должно быть? Почему случаи, когда H==X когда-либо проваливаются до последнего предложения?

2 ответа

Решение

В последнем пункте говорится, что при удалении X из списка может остаться элемент head (независимо от его значения). Prolog может использовать это предложение в любое время, когда сочтет нужным, независимо от того, является ли условие в предыдущем предложении верным или нет вернуться к этому предложению, если другое предложение не выполнено, или если вы указываете это сделать (например, путем выдачи ; на верхнем уровне, чтобы получить следующее решение). Если добавить условие, что элемент head может не совпадать X, он должен работать.

Редактировать: Удалено неверное утверждение, которое я первоначально открыл.

Когда вы используете (==)/2 для сравнения вам понадобится обратное в третьем правиле, т.е. (\==)/2, С другой стороны, такое определение уже не является чистым отношением. Чтобы увидеть это, рассмотрим deleteall([X],Y,Zs), X = Y.

Для чистого отношения нам нужно (=)/2 а также dif/2, Многие прологи, такие как SWI, YAP, B, SICStus, предлагают dif/2,

deleteall([],X,[]).
deleteall([H|T],X,Result) :- 
    H=X,
    deleteall(T,X,Result).
deleteall([H|T],X,[H|Result]) :-
    dif(H,X),
    deleteall(T,X,Result).

Посмотрите на ответы для deleteall([X,Y],Z,Xs)!

Изменить (через четыре года):

Более эффективно, но в том же духе, это можно записать с помощью if_/3 а также (=)/3:

deleteall([], _X, []).
deleteall([E|Es], X, Ys0) :-
   if_( E = X, Ys0 = Ys, Ys0 = [E|Ys] ),
   deleteall(Es, X, Ys).
Другие вопросы по тегам