好的,让我们发挥创意...您本质上需要一种方法来记住(通过回溯)If 条件至少有一个解决方案。动态谓词对我来说是一个禁忌,但还有其他选择吗?那么,ISO-Prolog 定义了一种匿名对象,stream-term,它可以(ab)用于以这种相当优雅的方式实现不可回溯标志:
if(If, Then, Else) :-
open(., read, S),
(
If,
close(S, [force(true)]),
Then
;
catch(close(S), error(existence_error(stream,_),_), fail), % fail if already closed
Else
).
我们关闭流以表明If 有一个解决方案,然后由 else 分支中的关闭尝试检测到。这在像ECLiPSe 这样的系统中完美且无泄漏。然而,许多系统(包括 XSB)重复使用封闭流的标识符(ISO 并未禁止),使得该解决方案不可移植。
但是等等,流有一个 position 属性,它可以设置,并且在回溯过程中保持它的值!使用这个技巧,XSB 上的以下工作:
if(If, Then, Else) :-
% open('ReadableAndNonemptyFile', read, S), % general ISO
open(atom(a), read, S), % XSB (needs no file)
stream_property(S, position(Zero)),
get_char(S, _),
(
catch(If, Ball, (close(S),throw(Ball))),
set_stream_position(S, Zero),
Then
; stream_property(S, position(Zero)) ->
close(S),
fail
;
close(S),
Else
).
遗憾的是,open(atom(...),...) 功能是特定于 XSB 的,对于严格的 ISO-Prolog,您需要一个虚拟文件...