-1

我只是从 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中则为真”,包含(L1,L2)被递归翻译,直到所有成员都被遍历我们只剩下最后一个选项,或者我们找到一个不在 L1 中的成员,它将使谓词失败。

不幸的是,它似乎不是那样工作的。好像只返回 member(X, L1) 的值,所以 contains([1,2,3],[1,4,5]) 就通过了,但是 contains([1,2,3],[4, 1,5])没有。

我究竟做错了什么?

4

2 回答 2

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).

是语法错误(谓词名称后不应有空格)。此外,如果更正,它会创建一个不需要的选择点。所以,宁愿删除它。

如果您想assert/1在 Prolog 提示符下使用,请执行

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

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

Yes

要查看知识库中的内容,请使用listing/0.

?- listing.

:- dynamic contains/2.

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

Yes

我认为问题不在于您在自己的答案中指出的“断言自由变量”。相反,请检查您的包围。

于 2009-06-27T22:47:37.750 回答
-2

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

于 2009-06-29T19:48:53.870 回答