2016-11-13 3 views
1
delete(X,[X|R],[_|R]). 
delete(X,[F|R],[F|S]) :- 
    delete(X,R,S). 

Выше мое определение удаления предиката, для удаления (X, L, R), предназначенный для удаления всех вхождений X в L с результатом R.ПРОЛОГА определения «Удалить» сказуемое

я опрошена ниже, и получите «G2397797». Для чего стоит эта строка?

?- delete(1,[1,2,3,4,5],X). 
X = [_G2397797, 2, 3, 4, 5] . 
+0

'delete (X, [X | R], [_ | R]).' Не просто удаляет 'X', но заменяет его анонимной переменной (' _'). Это то, что вы действительно хотите? – lurker

ответ

0

В ответ вы получите X = [_G2397797, 2, 3, 4, 5] ., _G2397797 не является строкой, это переменная, которая не создается экземпляр. Это связано с пунктом:

delete(X,[X|R],[_|R]). 

, который помещает в выходной список анонимную переменную «_». Вы можете написать delete(X,[X|R],R).

Но у этого есть несколько проблем. Во-первых, он удаляет только , а не X, потому что в приведенном выше пункте, когда вы найдете его, вы преуспеваете. Также вы не подумали о пустом списке, который также является базовым случаем рекурсии. Наконец, в вашем втором пункте вы не применили какое-либо правило, которое говорит F и X отличаются и это положение дают неправильные результаты, когда F равен X.

Таким образом, вы могли бы написать:

delete(_,[],[]). 
delete(X,[X|R],S):-delete(X,R,S). 
delete(X,[F|R],[F|S]):-dif(X,F),delete(R,S). 
+0

В документации по [библиотеке 'delete/3' в SWI-Prolog] есть очень показательный комментарий (http://eu.swi-prolog.org/pldoc/doc_for?object=delete/3), по крайней мере : "Устаревшее: слишком много способов удалить элементы из списка, чтобы оправдать имя. Подумайте о совпадении (' = 'vs.' == '), удалите first/all, детерминированным или нет. " В любом случае, я думаю, что удаление с помощью OP предназначалось для сопоставления с '=', сначала только, delete next on backtracking. –

+0

Я не совсем уверен, что я точно понимаю. Вы имеете в виду что-то вроде: delete (_, [], []). delete (X, [Y | R], S) :- (X = Y -> S = [X | T], delete (X, R, T); delete (X, R, S)). – coder

+0

Код в комментариях немного сложный; см. мой ответ –

1

Если вы просто правильно ваш первый раздел и удалить ненужные анонимную переменную, вы получите:

delete_each(X, [X|L], L). 
delete_each(X, [Y|Ys], [Y|Zs]) :- 
     delete_each(X, Ys, Zs). 

Это будет использовать объединение, и удалить каждое вхождение X в списке на возвратов:

?- delete_each(a, [a,b,a,c], R). 
R = [b, a, c] ; 
R = [a, b, c] ; 
false. 

Вы видите, как это идентично select/3?

Если вы хотите удалить все вхождения X в список, вы можете увидеть answer by @coder.