Prolog延迟评估:LIFO还是FIFO唤醒?

Tra*_*ers 7 prolog swi-prolog sicstus-prolog prolog-coroutining

许多Prolog系统都有一个freeze/2谓词,一个应该有名字的谓词,geler/2因为它甚至是在Prolog-II之前发明的.

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

 ?- freeze(X, G1), freeze(X, G2), X=1.
Run Code Online (Sandbox Code Playgroud)

什么是首选的唤醒策略,G1首先执行还是G2首次执行?如果G1和G2确实会产生新的冻结,这也会被唤醒:

 G1 :- freeze(Y, G3), Y=1.
 G2 :- freeze(Z, G4), Z=1. 
Run Code Online (Sandbox Code Playgroud)

G3或G4是否始终在G1和G2之间执行,或者可能是G1和G2之后执行G3或G4,甚至是以后的任何时间?

再见

小智 3

这在一定程度上取决于 freeze/2 的底层实现方式。可以发挥作用的属性变量接口的两种主要类型是关于唤醒的类型1和类型2。即:

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

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

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

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

SWI-Prolog:

?- 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.
Run Code Online (Sandbox Code Playgroud)

Jekejeke Prolog 与 Minlog 扩展:

?- 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
Run Code Online (Sandbox Code Playgroud)

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