由于我想避免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
函数将此尾/孔(变量)与成员的第一个参数统一起来。
我正在寻找一种方法,我可以检查打开列表中是否有与给定元素相等的元素。我怎么能这样做?
答案 0 :(得分: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).
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.