正在Prolog中停止无限循环



我正在尝试返回列表中不同的项。我想出了以下代码。在使用成员(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,但前提是Catdog不同。

最新更新