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 系统中从左到右执行。由此还可以推断,如果目标进一步冻结并立即自行唤醒,会发生什么情况。