1

事实证明,SICStus Prolog 没有occurrence_check Prolog 标志。至少我们找不到,这里给出了一条错误消息:

/* SICStus 4.6.0 (x86_64-win32-nt-4) */

?- set_prolog_flag(occurs_check, true).
Domain error in argument 1 of set_prolog_flag/2 

看起来“true”的值不是问题,关键的统一可以通过现有的内置unify_with_occurs_check/2. 一个发生检查 Prolog 标志的一个有趣的值是值“错误”。

如何实现谓词unify_with_occurs_check_and_error/2?请注意,unify_with_occurs_check_and_error/2 的解决方案应该表现得像 unify_with_occurs_check/2,即不触发属性变量。

以下是 Prolog 标志的示例用法:

?- set_prolog_flag(occurs_check, error).
true.

?- X = f(X).
ERROR: ...

这就是在 SICStus Prolog 中要做的事情:

?- unify_with_occurs_check_and_error(X, f(X)).
ERROR: ...
4

1 回答 1

0

正在从这里调整代码并得到以下解决方案:

unify_with_error(X, Y) :- var(X), var(Y), !, X = Y.
unify_with_error(X, Y) :- var(X), !, must_notin(X, Y), X = Y.
unify_with_error(X, Y) :- var(Y), !, must_notin(Y, X), X = Y.
unify_with_error(X, Y) :- functor(X, F, A), functor(Y, G, B),
   F/A = G/B,
   X =.. [_|L],
   Y =.. [_|R],
   maplist(unify_with_error, L, R).

must_notin(X, Y) :-
   term_variables(Y, L),
   maplist(\==(X), L), !.
must_notin(X, Y) :-
   throw(error(occurs_check(X, Y),_)).

似乎工作并且不干扰属性变量:

/* SICStus 4.6.0 (x86_64-win32-nt-4) */

?- unify_with_error(X, f(X)). 
error(occurs_check(_413,f(_413)),_409)

?- freeze(X, throw(ball)), unify_with_error(X, f(X)).
error(occurs_check(_413,f(_413)),_409)
于 2021-01-06T18:08:15.633 回答