问题描述
事实证明,SICStus 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: ...
解决方法
正在改编 here 中的代码并得到以下解决方案:
unify_with_error(X,Y) :- var(X),var(Y),!,X = Y.
unify_with_error(X,must_notin(X,Y),Y) :- var(Y),must_notin(Y,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),!.
must_notin(X,Y) :-
throw(error(occurs_check(X,_)).
似乎有效并且不干扰属性变量:
/* 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,_409)