微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何安全地临时更改发生检查标志?

如何解决如何安全地临时更改发生检查标志?

我正在使用以下代码临时更改发生检查标志,其中 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 举报,一经查实,本站将立刻删除。