获取缺失事实的谓词



我有一堆事实。

f(1, John).
f(2, Peter).
f(3, Gordon).
f(4, Bono).
f(5, Carl).
f(6, Mick).
check([], []) .
check([f(X, Y)|L1] , [f(X, Y)|L2] ) :-  f(X, Y), check(L1,L2).

如果我运行检查谓词

check([ f(1, John), f(3, Gordon), f(2, Peter), _, f(6, Mick), f(5, Carl)], Group).

应该打印。

Group = [ f(1, John), f(3, Gordon), f(2, Peter), f(4, Bono), f(6, Mick), f(5, Carl)].

黑色的空间填满了缺失的事实。但是我的程序正在打印。

Group = [ f(1, John), f(3, Gordon), f(2, Peter), f(1, John), f(6, Mick), f(5, Carl)].

它正在获取第一个事实。如何解决这个问题?

你混淆了两件事:回溯和迭代列表(通过尾部递归)。

此外,你有在你的"事实"数据库变量(John, Peter等),当你可能实际上去原子?(如john, peter,或者,如果你想大写,'John', 'Peter')。如果你试图编译它,你应该会看到一堆"单例变量"警告。这一边,

查询

?- f(X, Y).

将通过回溯

给你
X = 1, Y = john;
X = 2, Y = peter

等等

你写的谓词,check/2,迭代你给它的列表,它在每一步实际做的是检查是否有一个事实f(X, Y)适合你提供的XY。(同样,由于您的第二个参数目前是变量,因此这也不完全正确,但对于此解释并不重要)。

由于f(1, John)是第一个定义的事实,因此这是匹配的事实。如果你回溯,你也应该在同一个地方看到所有其他的事实。

但我不太清楚你到底想要达到什么目的。

编辑:

你想达到的目的很奇怪。你怎么知道你有多少空包弹?你必须了解所有的事实才能知道这一点。你是在整理你的事实吗?

这在之前的问题形式中已经解决了。下面是对该解决方案的一个简单改编:

f(1,john).
f(2,peter).
f(3,gordon).
f(4,bono).
f(5,carl).
f(6,mick).
check(L, C) :-
    check(L, [], C).
check([], _, []).
check([f(X,Name)|T], A, [f(X,Name)|C]) :-
    f(X, Name),
    + member(f(X, Name), A),
    check(T, [f(X,Name)|A], C).

这里的关键是,您必须携带到目前为止发现的内容(A),因为对于每个对check的新查询,对f的查询"重新开始"并从数据库的开头进行搜索。这不是回头路。但是,当我们检查成员关系并发现元素成员时,我们返回到f查询以获得下一个成员,直到我们遇到一个不属于我们迄今为止积累的列表的成员。

测试运行:

| ?- check([f(1,john), f(3,gordon), f(2,peter), _, f(6,mick), f(5,carl)], Group).
Group = [f(1,john),f(3,gordon),f(2,peter),f(4,bono),f(6,mick),f(5,carl)] ? a
no
| ?-

正如我链接的另一个答案所示,该技术将适用于多个空白。

你也可以不带"result "列表参数,在原始列表中实例化自由变量:

check(L) :-
    check(L, []).
check([], _).
check([f(X,Name)|T], A) :-
    f(X, Name),
    + member(f(X, Name), A),
    check(T, [f(X,Name)|A]).
| ?- X = [f(1,john), _, f(2,peter), _, f(6,mick), f(5,carl)], check(X).
X = [f(1,john),f(3,gordon),f(2,peter),f(4,bono),f(6,mick),f(5,carl)] ? a
X = [f(1,john),f(4,bono),f(2,peter),f(3,gordon),f(6,mick),f(5,carl)]
(1 ms) no
| ?-

注意,如果您想使用大写的名称,可以将它们括在单引号中,这样它们就是原子,而不是变量。例如:f(1, 'John') .

最新更新