abs*_*ted 2 prolog terminate non-termination failure-slice
所以
?- canCall(mary, Person).
Run Code Online (Sandbox Code Playgroud)
工作并终止,
?- canFind(mary, Person).
Run Code Online (Sandbox Code Playgroud)
也可以工作并终止。但是不知何故
?- canCall(mary, Person), canFind(mary, Person).
Run Code Online (Sandbox Code Playgroud)
不终止。可能是什么原因?
(您实际上的意思是:查询会个别终止,但有时它们的连词不会终止)
您在这里发现了Prolog端接属性的一个非常基本的方面。让我们用下面的纯1程序看一下:
canFind(mary, john).
canCall(mary, bob).
canCall(A, B) :-
canCall(B, A).
?- canCall(mary, Person).
Person = bob
; ...
?- canFind(mary, Person).
Person = john.
Run Code Online (Sandbox Code Playgroud)
一切都很好!让我们签入此代码,以便每个人都可以使用它。现在,您不幸的同事尝试:
?- canCall(mary, Person), canFind(mary, Person).
* LOOPS *
Run Code Online (Sandbox Code Playgroud)
哦,不,这循环了!也许我只需要重新排列目标:
?- canFind(mary, Person), canCall(mary, Person).
* LOOPS *
Run Code Online (Sandbox Code Playgroud)
再次!
当然,你也心烦意乱。毕竟,您已经认真测试了此代码。它终止了。还是呢?
这是Prolog中最令人困惑的事情之一:在这里(至少)有两个不同的查询终止概念。您测试的一个(有时)称为存在终止。但是,我宁可建议将其称为查找答案。如您所见,它非常脆。
并且,如果查询不仅找到答案,还找到所有答案并完成查询,则这称为通用终止或简称终止。如果Prolog程序员说查询终止,则表示该查询普遍终止。
那么我们如何观察通用终止呢?只需索取所有答案。在GNU-Prolog中,键入a。在其他系统中,您将不得不锤击SPACE或;Return直到完成,否则您疲倦的眼睛或腕管会阻止它。
?- canCall(mary, Person).
Person = bob
; Person = bob
; Person = bob
; Person = bob
; Person = bob
; ...
Run Code Online (Sandbox Code Playgroud)
因此,在这里我们看到有无限多个答案(实际上,我们有限的生物必须证明这一点,但暂时要相信我)。
有没有便宜的方法可以观察到这一点?没有答案的墙吗?您可以通过添加永远不会成立的条件来“关闭”答案false。
因此,请问:
?-canCall(mary,Person),false。
这样查询的结果是什么?永远不可能true。它只能是false,应该终止。因此,与此查询我们简单地测试程序的终止性质只。
现在,两个(通用)终止查询的结合将始终终止。因此,这种终止更加健壮。
通用终端还有许多其他很酷的特性。例如,您可以根据需要交换子句的顺序(即事实和规则):不管子句的顺序如何,所有程序都共享完全相同的终止属性。
另一个是,您可以借助故障切片轻松地在程序中找到不终止的来源。开始阅读这一本。
在面向命令的编程语言中,这个概念并不容易出现。但是,对于迭代器,您有非常相似的概念:如果迭代器产生第一个项目,则该项目将对应于存在终止;如果产生了有限的多个项目,即,如果在有限的多个项目next完成之后,则将对应于通用终止。的种类。
1实际上,在不纯正的程序中,您有各种各样的荒谬行为。因此,考虑它们是没有意义的。