要重复,令人惊讶地失败是查询:
?- tem(graph(_, E)), adjacent(a, b, E).
false.
在Prolog,一个很好的方式来定位exacte 导致这样的问题是想 声明,并系统地尝试适合概括和专业您的计划和目标。
例如,可以通过分别与变量A
和 B
更换a
和 b
,使上述显著更一般查询:
?- tem(graph(_, E)), adjacent(A, B, E).
false.
所以,这仍然失败!因此,具体而言,因为程序完全是纯和 单调,所以更具体的查询也将失败 ,这使得这样的推理是可接受的。
让我们继续这和推广adjacent/2
的单一目标。
相反的:
adjacent(X,Y,graph(_,E)):-
member(e(X,Y), E).
我现在写的:
adjacent(X,Y,graph(_,E)) :-
true.
当然,这使得整个谓语显著更 一般:在原来的谓词成功任何情况下,这种变种将成功 也!
即使有这种显著更一般的定义,我们仍然有:
?- tem(graph(_, E)), adjacent(A, B, E).
false.
而且现在没有更多的遗体找到:错误必须在剩余部分,并在以下ERGO片段:
adjacent(X, Y, graph(_,E)) :- ...
如果你仔细观察,它是这一条款头导致失败:要调用ŧ他以 列表谓词作为第三个参数,但在此定义中,第三个参数是而不是 a 列表。
这种方法被称为声明调试,你将在program-slicing找到更多信息。一般而言,Prolog和逻辑编程语言对于允许应用这种功能强大的调试技术非常独特。注意,这种方法可以很容易地自动化:通过简单地断言,该查询应该成功,一个 程序可能得出上面的片段和你显示的 问题的确切原因。
一个好的命名约定是使用以“s”结尾的变量来表示* lists *。例如:'graph(_,Es)'。这更清楚地表明'Es'是一个列表。相比之下,当使用'相邻(a,q,G)'时,我希望'G'不*是一个列表。 – mat