打开列表和成员

Open list and member

因为我想避免 append/3 的成本,我使用 difference/open 个列表。

然而,开放列表的问题是 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] 

这是正确的行为,因为开放列表有一个无界的 "tail" 并且 member/2 函数将此 tail/hole(变量)与成员的第一个参数统一起来。

不过,我正在寻找一种方法来检查打开列表中是否有与给定元素相等的元素。我该怎么做?

您可以编写自己的 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).

Predicate 假设开放列表的尾部为 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.