许多谓词基本上使用某种形式的传递闭包,只是发现终止也必须得到解决.为什么不一次解决这个问题closure0/3:
:- meta_predicate closure0(2,?,?).
:- meta_predicate closure(2,?,?).
:- meta_predicate closure0(2,?,?,+). % internal
closure0(R_2, X0,X) :-
closure0(R_2, X0,X, [X0]).
closure(R_2, X0,X) :-
call(R_2, X0,X1),
closure0(R_2, X1,X, [X1,X0]).
closure0(_R_2, X,X, _).
closure0(R_2, X0,X, Xs) :-
call(R_2, X0,X1),
non_member(X1, Xs),
closure0(R_2, X1,X, [X1|Xs]).
non_member(_E, []).
non_member(E, [X|Xs]) :-
dif(E,X),
non_member(E, Xs).
Run Code Online (Sandbox Code Playgroud)
是否存在此定义不能用于实现传递闭包的情况?
详细回答@ WouterBeek的评论:dif/2或者iso_dif/2是理想的,因为它们能够显示或发出潜在问题的信号.但是,在当前的实现中,顶级循环通常会隐藏实际问题.考虑一下closure0(\_^_^true,a,b)本身肯定存在问题的目标.使用以下系统时,实际问题直接不可见.
| ?- closure0(\_^_^true,a,b). % SICStus
yes
?- closure0(\_^_^true,a,b). % SWI
true ;
true ;
true ...
Run Code Online (Sandbox Code Playgroud)
两个顶级循环都没有显示我们真正想要看到的内容:悬空约束.在SICStus中,我们需要一个伪变量来产生一些替换,在SWI中,查询必须被包装call_residue_vars/2.以这种方式,现在显示所有附加约束的变量.
| …Run Code Online (Sandbox Code Playgroud)