Открытый список и член

Так как я хочу избежать стоимости 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 Функция объединяет этот хвост / отверстие (переменную) с первым аргументом члена.

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

1 ответ

Решение

Вы можете написать свою собственную версию 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, Если предикат находит такой хвост, он выполняет разрез (!) и терпит неудачу.

Демо:

?- 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.
Другие вопросы по тегам