我如何模拟soft cut I *-> T;在ISO Prolog中是E?我有副作用,所以我不能多次称呼它。
除了最后一个要求,我认为以下定义有效:
if_(I, T, E) :-
not(not(I)) ->
call((I, T));
call((not(I), E)).
(我实际上正在使用XSB序言;对于XSB的解决方案对我也将很有用。)
最佳答案
Yes, we can在ISO Prolog甚至XSB中实现了这一点,但是效率不是很高。为了提高效率,您将需要一些“选择性剪切”。此外,XSB没有实现符合ISO的整数,因此必须单独处理溢出。
:- dynamic(if_counter/1).
if_counter(0).
:- dynamic(no_if_answer/1).
if(If_0, Then_0, Else_0) :-
once(if_counter(Id)),
Idx is Id+1,
( Idx > Id -> true
; throw(error(representation_error(max_integer),
'XSB misses ISO conforming integers'))
),
retractall(if_counter(_)),
asserta(if_counter(Idx)),
asserta(no_if_answer(Id)),
( If_0,
retractall(no_if_answer(Id)),
Then_0
; retract(no_if_answer(Id)) ->
Else_0
).
效率低下的主要根源是,对于确定条件
If_0
,仍然有一个选择点。难以想象的是,一旦执行了retract(no_if_answer(Id))
,实现可能会得出结论retractall(no_if_answer(Id))
总是会失败,这是不可思议的,但是我怀疑实现者会在这种优化上进行投资。编辑:这样做似乎不太可能的原因是,一个实现必须保证所断言的数字总是上升。请注意,软剪切会以与剪切相同的方式产生不完整性。考虑:
| ?- if(X = a, T = equal, T = not_equal).
X = a
T = equal;
no
这显然错过了答案!要了解原因,请使用
X = b
:| ?- X = b, if(X = a, T = equal, T = not_equal).
X = b
T = not_equal;
no
| ?- if(X = a, T = equal, T = not_equal), X = b.
no % bad!!
结点应该是可交换的(模非终止,错误,副作用)。
如果您对声明性的,有条件的条件感兴趣,这些条件也非常有效并且通常比不纯的条件要快,请考虑使用
if_/3
。有关SICStus的信息,请参见 library(reif)
,它给出了所有正确的答案:| ?- if_(X = a, T = equal, T = not_equal).
X = a,
T = equal ? ;
T = not_equal,
prolog:dif(X,a) ? ;
no
关于prolog - 如何在Prolog中模拟软切?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40620465/