我想为 Prolog 设计一个没有错误的顶级接口(其中
!
成功地削减了选择点,而不是 if-then
导致选择点被错误地削减)。我想我可以将 if-then
转换为先行词的真实性被具体化并在每个子句的开头测试其真实性的子句。
例如,下面的
test1
显示了原始的if-then子句。
test1:-(a1(1)->b1;c1).
a1(1).
b1.
c1.
在这里,
test2
显示了if-then
是如何被转换成单独的从句的。所以,test1.
和 test2.
做同样的事情,但是 test2
的选择点可以被削减,这与 if-then
中的 test1
子句相反,可能导致选择点被错误地削减。
test2:-a2(1,R),d2(R).
a2(1,true):-!.
a2(_,false).
d2(true):-b2,!.
d2(false):-c2.
b2.
c2.
作为决定论的例子:
member_other(Elem, Lst, Elem) :-
member(E, Lst),
( ?=(E, Elem)
% Found a match (so cannot be other)
-> E = Elem, !
; E = Elem
).
member_other(Elem, _Lst, other(Elem)).
swi-prolog 中的结果:
?- member_other(E, [a,b], O).
E = O, O = a ;
E = O, O = b ;
O = other(E).
?- member_other(b, [a,b], O).
O = b. % Nice determinism
?- member_other(c, [a,b], O).
O = other(c). % Nice determinism
如果选项有重叠,则可以将最后一个谓词更改为:
member_other(Elem, Lst, other(Elem)) :-
maplist(dif(Elem), Lst).
在
library(reif)
的帮助下,也可以具体化更复杂的条件。特别是任何具体化条件的连词和析取。因此,事实可以编码为连词(每个参数一个=
)的析取(每个事实一个选择)。当然,无论是直切还是像*->
这样的软切都不能单独解决这个问题。有关此类示例,请参见char_class/2
。
为了更好地说明
library(reif)
的用法,这里是@brebs的member_other/3
的正确实现。它与 brebs 期望的一样确定,此外它对于 brebs 的实现被破坏的情况也是正确的:
member_other(E, Lst, Elem) :-
if_(memberd_t(E, Lst), E = Elem, other(E) = Elem).
?- member_other(E, [a,b], O).
E = a, O = a
; E = b, O = b
; O = other(E), dif(a,E), dif(b,E).
?- member_other(b, [a,b], O).
O = b.
?- member_other(c, [a,b], O).
O = other(c).
?- member_other(a, [a], other(a)).
false.
这是 SICStus 的扩展:
member_other(A,B,C) :-
reif:memberd_t(A,B,D),
( D==true ->
A=C
; D==false ->
other(A)=C
; nonvar(D) ->
throw(error(type_error(boolean,D),type_error(call(user:memberd_t(A,B),D),2,boolean,D)))
; throw(error(instantiation_error,instantiation_error(call(user:memberd_t(A,B),D),2)))
).