我正在使用以下代码临时更改发生检查标志,其中 G 是一个不会创建任何延迟目标的目标:
with_occurs_check(G) :-
current_prolog_flag(occurs_check, F),
setup_call_cleanup(
set_prolog_flag(occurs_check, true),
G,
set_prolog_flag(occurs_check, F)).
下面是 with_occurs_check/1 的一个期望方面,因为我们希望所有回溯到目标 G 工作,并将发生检查标志设置为 true。最好只在创建选择点后,在 SWI-Prolog 中可以看到“;” 只问一次而不是两次:
?- with_occurs_check((X=1;current_prolog_flag(occurs_check, F), X=2)).
X = 1 ;
X = 2,
F = true. %%% desired
但有一个警告。当 G 是非确定性的时,上述内容实际上并不适用。如果 G 有一个带有剩余选择点的出口端口,setup_call_cleanup/3将不会调用它的清理。因此发生的检查标志更改将泄漏到延续中:
?- with_occurs_check((X=1;X=2)), current_prolog_flag(occurs_check, F).
X = 1,
F = true ; %%% not desired, update leaking
X = 2,
F = false. %%% desired
有没有更安全的方法来临时更改发生检查?