2016-06-07 2 views
2

Поскольку я хочу избежать стоимости append/3, я использую разницу/открытые списки.Открытый список и член

Проблема с открытым списком однако заключается в том, что member/2 реагирует на открытый список, добавляя элемент в хвост. Например:

?- L=[a|_],member(b,L). 
L = [a, b|_G1196] ; 
L = [a, _G1195, b|_G1199] ; 
L = [a, _G1195, _G1198, b|_G1202] ; 
L = [a, _G1195, _G1198, _G1201, b|_G1205] ; 
L = [a, _G1195, _G1198, _G1201, _G1204, b|_G1208] ; 
L = [a, _G1195, _G1198, _G1201, _G1204, _G1207, b|_G1211] 

Это правильное поведение, так как открытый список имеет неограниченный «хвост» и функция member/2 объединяет этот хвост/отверстие (переменный) с первым аргументом члена.

Я смотрю, однако, таким образом, я могу проверить, есть ли в открытом списке элемент, равный данному элементу. Как я могу это сделать?

+2

Пожалуйста, покажите код. – Rudi

ответ

3

Вы можете написать свой собственный вариант member/2: member_open/2:

member_open(_,X) :- 
    var(X), 
    !, 
    fail. 
member_open(X,[X|_]). 
member_open(X,[_|T]) :- 
    member_open(X,T). 

или более чище Подход:

member_open(X,Y) :- 
    \+var(Y), 
    Y = [X|_]. 
member_open(X,Y) :- 
    \+var(Y), 
    Y = [_|T], 
    member_open(X,T). 

предиката делает предположение о том, что открытый список имеет хвост, который var/1 , Если предикат находит такой хвост, он выполняет разрез (!) и терпит неудачу.

Demo:

?- member_open(a,[]). 
false. 

?- member_open(a,[a]). 
true ; 
false. 

?- member_open(a,[a,a]). 
true ; 
true ; 
false. 

?- member_open(a,[a,a|_]). 
true ; 
true ; 
false. 

?- member_open(b,[a,a|_]). 
false. 

?- member_open(X,[X,a|_]). 
true ; 
X = a ; 
false. 

?- member_open(X,[c,a|_]). 
X = c ; 
X = a ; 
false. 
+0

ОК, спасибо. Пожалуйста, скажите мне одну вещь: Является ли это чистым в смысле пролог/логической парадигмы программирования? У меня нет опыта в этой парадигме, и для меня это проблематично. – Gilgamesz

+2

@Gilgamesz: Проблема в том, что нет общепринятого определения (https://www.w3.org/2005/rules/wg/wiki/Pure_Prolog .html). Но поскольку он использует разрез, это, вероятно, не так. Однако вы можете переписать его на вариант «* более чистый» (между кавычками). Хотя 'var' также можно считать нечистым ... Если ваше определение довольно строгое, я думаю, что невозможно реализовать такой предикат' member_open/2'. –

+3

Это, безусловно, ** не ** логическое отношение, так как например: '? - член (E, Ls). ** ** терпит неудачу ** (декларативно это означает: есть * нет решений *), но a * более конкретный * запрос ** преуспевает **, например: '? - member (E, [E | _]).'. Из чистых логических отношений мы * конечно * ожидаем, что если конкретный запрос будет успешным, то * более общий * запрос * не сработает *. – mat