我正在尝试返回列表中不同的项。我想出了以下代码。在使用成员(X,Y(检查列表的成员时,我似乎遇到了一个问题,它进入了一个无限循环。
get_unique(Y, [H|T]) :-
memberchk(H, Y)-> get_unique(Y, T) ; get_unique([H|T], T).
get_unique(_, []) :- true.
final_list(X, L) :-
get_unique(Y, L), member(X,Y).
有两种输入情况:
?- final_list(dog,[dog,cat,bat,dog]).
true;
true;
true;
true;
(infinitely)
在这种情况下,我只希望
true;
false.
另一种输入情况:
?- final_list(X,[dog,cat,bat,dog]).
X = dog;
X = cat;
X = bat;
true ;
true ;
true ;
true ;
true ;
true ;
(infinitely)
在这种情况下,我只希望
X = dog;
X = cat;
X = bat;
false.
我试着做了一些调试,我想我可以看到成员(X,Y(正在生成无限循环——跟踪下面的步骤。我不知道如何阻止这种情况,这样成员一旦返回蝙蝠就停止检查。
X = bat ;
Redo: (9) lists:member(_6632, [dog, cat, bat|_6882]) ? creep
Exit: (9) lists:member(_6632, [dog, cat, bat, _6632|_6888]) ? creep
Exit: (8) final_list(_6632, [dog, cat, bat, dog]) ? creep
true ;
Redo: (9) lists:member(_6632, [dog, cat, bat, _6886|_6888]) ? creep
Exit: (9) lists:member(_6632, [dog, cat, bat, _6886, _6632|_6894]) ? creep
Exit: (8) final_list(_6632, [dog, cat, bat, dog]) ? creep
true ;
Redo: (9) lists:member(_6632, [dog, cat, bat, _6886, _6892|_6894]) ? creep
Exit: (9) lists:member(_6632, [dog, cat, bat, _6886, _6892, _6632|_6900]) ? creep
Exit: (8) final_list(_6632, [dog, cat, bat, dog]) ? creep
true ;
Redo: (9) lists:member(_6632, [dog, cat, bat, _6886, _6892, _6898|_6900]) ? creep
Exit: (9) lists:member(_6632, [dog, cat, bat, _6886, _6892, _6898, _6632|...]) ? creep
Exit: (8) final_list(_6632, [dog, cat, bat, dog]) ? creep
true ;
谢谢!
单独尝试get_unique/2
:
?- get_unique(Y,[dog,cat,bat,dog]).
Y = [dog,cat,bat|_A].
% ^^^
因此,Y
只是部分列表,而不是(真实的(列表。它包括具有三个或三个以上元素的所有列表。
第二个子句应该读成get_unique([], []).
以避免这个问题。第一个需要重新安排:
get_unique(Y, [H|T]) :-
( memberchk(H, T) -> get_unique(Y, T) ; Y = [H|Y1], get_unique(Y1, T) ).
% ^^ ^^^^^^^^^^ ^^
get_unique([], []).
但是,你的定义仍然有一些奇怪的假设:
?- final_list(X,[dog,Cat]).
X = dog, Cat = dog.
因此,它迫使变量变成一个特定的值。
除了重新考虑member/2
之外,没有什么干净的方法可以解决这个问题。请参阅此答案以获得干净的解决方案。以下是memberd/2
产生的答案:
?- memberd(X,[dog,Cat]).
X = dog
; X = Cat, dif(Cat,dog)
; false.
所以答案是:X = dog
和以前一样,另外,X = Cat
,但前提是Cat
和dog
不同。