Prolog谓词问题

Prolog谓词问题,prolog,Prolog,我只是从Prolog开始,我不明白为什么下面的代码不能像我期望的那样工作。 我试图创建一个谓词,如果列表L2包含在L1中,它将返回true。 这是我写的: assert(contains (L1, L1)). assert(contains(L1, [X|L2]):-member(X, L1), contains(L1, L2)). assert(contains(L1, [])). 我认为这相当于如果'L3=X | L2'的X在L1中,L2也在L1中,则为true,containsL1,L2

我只是从Prolog开始,我不明白为什么下面的代码不能像我期望的那样工作。 我试图创建一个谓词,如果列表L2包含在L1中,它将返回true。 这是我写的:

assert(contains (L1, L1)).
assert(contains(L1, [X|L2]):-member(X, L1), contains(L1, L2)).
assert(contains(L1, [])).
我认为这相当于如果'L3=X | L2'的X在L1中,L2也在L1中,则为true,containsL1,L2被递归转换,直到所有成员都被遍历,剩下最后一个选项,或者我们找到一个不在L1中的成员,它将使谓词失败

不幸的是,它似乎不是那样工作的。它似乎只返回memberX,L1的值,因此包含[1,2,3],[1,4,5]个过程,但包含[1,2,3],[4,1,5]个过程


我做错了什么

我没有完全理解你的问题,但我会这样写contains/2谓词:

% An empty list is contained by any list
contains(_, []).

% If a list is not empty, then its
% first element must be an element of L1,
% and its tail must be contained by L1.
contains(L1, [X | L2]) :-
    member(X, L1),
    contains(L1, L2).
顺便说一句,注意你的第一条规则是事实

contains (L1, L1).
是一个语法错误,谓词名称后不应该有空格。 此外,如果更正,将创建不需要的choicepoint。所以,还是删除它吧

如果要在Prolog提示符上使用assert/1,请执行

?- assert(contains(_, [])).

Yes
?- assert(contains(L1, [X | L2]) :- (member(X, L1), contains(L1, L2))).

Yes
要查看知识库中的结果,请使用清单/0


我认为问题不在于像您在自己的答案中指出的那样断言自由变量。更确切地说,检查括号。

显然,对自由变量使用断言至少在这个版本中会导致问题,所以这就是它行为不当的原因。删除断言并使用consultfile命令解决了这个问题

您使用的是哪种Prolog实现?我无法在SWI Prolog中重现您的问题,尽管它在那里也不太有效。2.7.12?真正地尝试一些更新的东西,比如5.6.x或5.7.x。我尝试了你问的问题,但它有相同的问题:如果我调用contains[1,2,3],[1,2,4],它会用yesStrange回复,在我的情况下,它会回复false。你最初的问题与assert无关。你到底断言了什么?我基本上是在提示符中写的,所以我断言了一切。将断言添加到发布的代码中。
?- listing.

:- dynamic contains/2.

contains(_, []).
contains(B, [A|C]) :-
    member(A, B),
    contains(B, C).

Yes