所以我试图在序言中编写一个谓词,它可以采用列表 L1 和列表 L2 并返回 L1 中不在 L2 中的所有元素的列表。这是我到目前为止所拥有的:
% Append an element to a list.
myappendelem(X,L,[X|L]).
% True if input list contains X.
mycontains([H | T], X) :-
H == X;
mycontains(T,X).
% Does the work for notin().
nocontains([],_,A,A).
nocontains([H|T],L,A,R):-
mycontains(L,H),
nocontains(T,L,A,R);
myappendelem(H,A,AR),
nocontains(T,L,AR,R).
% Returns all elements in L1 not in L2.
notin(L1,L2,R):-
nocontains(L1,L2,[],X).
这可行,但是它给出了多个答案,例如:
notin([5,1],[4,3,2,1],X).
X = [5];
X = [5,1].
这是一个问题,因为我正在使用这个谓词来整理图中的路径(L1 是我可能去的节点列表,L2 是我已经去过的节点)以确保我不会再访问同一个节点不止一次并陷入循环。但是这个实现让我陷入了一个循环,因为它在尝试使用第一个 X 并且失败后回溯到未更改的 X,进入可以相互到达的相同两个节点之间的无限循环。我知道这很容易通过向 nocontains 添加削减来解决,如下所示:
% Does the work for notin().
nocontains([],_,A,A).
nocontains([H|T],L,A,R):-
mycontains(L,H),!,
nocontains(T,L,A,R);
myappendelem(H,A,AR),!,
nocontains(T,L,AR,R).
但是有没有办法在不削减的情况下达到同样的效果?所以当我使用 notin 时,我只能得到一个可能的答案?(它是针对学校的,部分任务是不使用任何内置谓词或控制运算符)
编辑:
只是为了更具体地说明赋值的限制:它应该由纯事实和规则组成,我们不允许使用任何内置的谓词或控制结构(包括但不限于算术,削减或否定作为失败)。分号没问题。我们需要定义自己的任何实用谓词。
感谢所有答案,但我开始认为我用于在图中查找两个节点之间的路径的方法可能是一个问题,因为从答案来看,似乎没有简单的方法这个。