如何解决如何安全地临时更改发生检查标志?
我正在使用以下代码临时更改发生检查标志,其中 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,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
有没有更安全的方法来临时更改发生检查?
解决方法
也许在 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)),F)).
试运行:
?- with_occurs_check((X=1;X=2)),current_prolog_flag(occurs_check,F).
X = 1,F = false ;
X = 2,F = false.
阅读评论后更新,以便在回溯时发生_检查继续为真:
with_occurs_check(G) :-
current_prolog_flag(occurs_check,with_occurs_check1(F)),F)).
with_occurs_check1(F):-
set_prolog_flag(occurs_check,F).
with_occurs_check1(_):-
set_prolog_flag(occurs_check,fail.
样品运行:
?- with_occurs_check((X=1;current_prolog_flag(occurs_check,X=2)),F2).
X = 1,F2 = false ;
X = 2,F = true,F2 = false ;
false.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。