冻结/2 的意外行为

rep*_*eat 11 prolog sicstus-prolog prolog-coroutining

我在玩谓词freeze/2frozen/2

?- freeze(X,a=a), frozen(X,Goal).
?- freeze(X,a=a), freeze(Y,b=b), X=Y, frozen(X,Goal).
Run Code Online (Sandbox Code Playgroud)

(x86_64 的 4.5.1 版)给出了这些答案:

| ?- 冻结(X,a=a),冻结(X,目标)。
目标 = prolog:freeze(X,user:(a=a)) ,
序言:冻结(X,用户:(a = a))?;
不
| ?- 冻结(X,a=a),冻结(Y,b=b),X=Y,冻结(X,目标)。
Y = X,
目标 = (user:(a=a),prolog:freeze(X,user:(b=b))) ,
序言:冻结(X,用户:(a = a)),
序言:冻结(X,用户:(b = b))?;
不

现在没想到!Goal = prolog:freeze(X,user:(a=a))

期望的是像 8.0.3 版给出的答案:

?- 冻结(X,a=a),冻结(X,目标)。
目标 = 用户:(a=a) ,
冻结(X,a = a)。
?- 冻结(X,a=a),冻结(Y,b=b),X=Y,冻结(X,目标)。
X = Y,
目标 = (用户:(a=a), 用户:(b=b)) ,
冻结(Y,a = a),
冻结(Y,b = b)。

可以说,SICStus 的答案SWI 的答案都是正确的......

但是,对于 SICStus 给出的有些奇怪的答案是否有更深层次的原因?

Per*_*ner 7

我不知道这种差异是否有任何“深层”原因。因为它frozen/2是属性变量的通用接口,所以不是特殊情况freeze/2目标是有意义的。

事实上,在 4.5.1 之前,SICStus 尝试过,但有时失败了,以实现特殊情况freeze/2目标。这就是您看到user:(a=a)第一个子目标的原因。在下一个版本中,我们对此进行了更改,因此结果将变为Goal = (prolog:freeze(X,user:(a=a)),prolog:freeze(X,user:(b=b)))(并且我们还对 进行了一些其他改进frozen/2)。