8

许多 Prolog 系统都有一个freeze/2谓词,这个谓词可能应该有这个名字geler/2,因为它甚至在 Prolog-II 之前就被发明了。

假设我对同一个变量有一个条件,但有两个不同的目标,即:

 ?- freeze(X, G1), freeze(X, G2), X=1.

首选的唤醒策略是什么,是先执行 G1 还是先执行 G2?如果 G1 和 G2 确实产生了新的冻结,它们也被唤醒了怎么办:

 G1 :- freeze(Y, G3), Y=1.
 G2 :- freeze(Z, G4), Z=1. 

G3或G4总是在G1和G2之间执行,还是G3或G4在G1和G2之后执行,甚至更晚?

再见

4

1 回答 1

3

这取决于如何在引擎盖下实现 freeze/2 。可以发挥作用的两种主要类型的属性变量接口是关于唤醒的类型 1 和类型 2。即:

类型 1:统一
后 唤醒将在 X 被实例化并且当前目标成功之后,在调用下一个目标之前发生。使用这种类型,冻结的目标会看到任何实例化,但执行不是立即的,而且并非总是如此。

类型 2:预统一
唤醒将在统一期间实例化 X 之前发生。预统一对 freeze/2 没有任何意义,因为那时冻结的目标不会看到任何实例化。

在上面的例子中,成功的目标是 X=1,下一个目标是查询结束的伪目标。从变量的属性值中读取的唤醒目标被推送到列表中,以便它们可用于下一个目标。

让我们看看这个列表是否是一个 FIFO:

SWI-序言:

?- freeze(X, write('ha ')), freeze(X, write('tschi ')), X=1, nl.
ha tschi 
X = 1.

?- freeze(X, write('ha ')), freeze(X, write('tschi ')), (X=1; X=2), nl.
ha tschi 
X = 1 ;
ha tschi 
X = 2.

带有 Minlog 扩展的 Jekejeke Prolog:

?- use_module(library(term/suspend)).
% 5 consults and 0 unloads in 90 ms.
Yes

?- freeze(X, write('ha ')), freeze(X, write('tschi ')), X=1, nl.
ha tschi 
X = 1

?- freeze(X, write('ha ')), freeze(X, write('tschi ')), (X=1; X=2), nl.
ha tschi 
X = 1 ;
ha tschi 
X = 2

所以这个列表是一个FIFO。如此冻结并立即醒来,在上述两个 Prolog 系统中从左到右执行。从这一点也可以推断如果目标进一步冻结并立即自行唤醒会发生什么。

于 2018-05-19T21:24:51.060 回答