Prolog子句单独终止,但不能一起终止

时间:2016-04-04 15:45:09

标签: prolog terminate failure-slice non-termination

所以

?- canCall(mary, Person).

工作并终止和

?- canFind(mary, Person).

也可以工作和终止。但不知何故

?- canCall(mary, Person), canFind(mary, Person). 

不会终止。可能是什么原因?

2 个答案:

答案 0 :(得分:5)

(你的意思是:查询单独终止,但有时它们的连接不会终止)

您在这里发现了Prolog终止属性的一个非常基本的方面。让我们看看以下纯 1 程序:

canFind(mary, john).

canCall(mary, bob).
canCall(A, B) :-
   canCall(B, A).

?- canCall(mary, Person).
   Person = bob
;  ... 

?- canFind(mary, Person).
   Person = john.

一切都很好看!让我们检查一下这个代码,这样每个人都可以使用它。现在你的倒霉的同事试图:

?- canCall(mary, Person), canFind(mary, Person).
* LOOPS *

哦不,这循环!也许我只需要重新排列目标:

?- canFind(mary, Person), canCall(mary, Person).
* LOOPS *

再次!

当然,你不开心了。毕竟,你努力测试了这段代码。它终止了。还是做到了?

两种终止概念

这是Prolog中最令人困惑的事情之一:我们在这里(至少)有两种不同的终止查询的概念。您测试的那个(有时)称为存在性终止。但是,我建议简单地称之为找到答案。你经历过的时候非常脆弱。

如果查询不仅找到答案,而且全部,并完成查询,那么这称为通用终止或只是终止。如果Prolog程序员说查询终止,则意味着它终止普遍。

那么我们如何观察全面终止呢?只需要求所有答案。在GNU-Prolog中,键入 a 。在其他系统中,你必须锤击 SPACE ; 返回直到它完成,或者你疲惫的眼睛或你的腕管阻止它。

?- canCall(mary, Person).
   Person = bob
;  Person = bob
;  Person = bob
;  Person = bob
;  Person = bob
;  ...

所以在这里我们看到有无限多的答案(实际上,我们有限的人必须证明这一点,但暂时相信我。)

是否有更便宜的观察方式?没有所有这些答案文本的墙壁?您可以通过添加一个永远不会成立的条件来“关闭”答案, false

所以请改为:

?- canCall(mary, Person), false.

此类查询的结果可能是什么?它永远不会是true。如果它终止,它只能是false。因此,通过此查询,我们只需测试程序 的终止属性。

现在,两个(通用)终止查询的连接将始终终止。所以这种终止更加健壮。

通用终端还有很多很酷的特性。例如,您可以根据需要交换子句的顺序(即事实和规则):无论它们处于什么顺序,所有程序都共享完全相同的终止属性。

另一个原因是,您可以借助轻松找到程序中的非终止来源。用this one开始阅读。

在面向命令的编程语言中,这个概念并不容易出现。但是,对于迭代器,你有非常相似的概念:如果迭代器产生第一个项目,那将对应于存在性终止,如果产生有限的许多项目,也就是说,如果在有限多个next之后它完成了,那就会对应于通用终止。那种。

1实际上,在不纯的程序中,你有各种荒谬的行为。因此,考虑它们毫无意义。

答案 1 :(得分:0)

我猜,当您单独运行时,col = ss.GetActiveCol(); row = ss.GetActiveRow(); 会统一为两个不同的值。检查一下。