我有这个跟踪元解释器。它是为swi-prolog编写的。
trace(Goal):-
trace(Goal, 0).
trace(true, _Depth):-!, true.
trace(fail, _Depth):-!, fail.
trace(A > B, _Depth):-!, A > B.
trace(A < B, _Depth):-!, A < B.
trace(A <= B, _Depth):-!, A <= B.
trace(A >= B, _Depth):-!, A >= B.
trace(A = B, _Depth):-!, A = B.
trace(A is B, _Depth):-!, A is B.
trace(!, _Depth):-!, fail.
trace(not(A), _Depth):-!, not(A).
trace((Goal1, Goal2), Depth):-!,
trace(Goal1, Depth),
trace(Goal2, Depth).
trace(Goal, Depth):-
display('Call: ', Goal, Depth),
clause(Goal, Body),
Depth1 is Depth + 1,
trace(Body, Depth1),
display('Exit: ', Goal, Depth),
display_redo(Goal, Depth).
trace(Goal, Depth):-
display('Fail: ', Goal, Depth),
fail.
display(Message, Goal, Depth):-
tab(Depth), write(Depth), write(': '), write(Message),
write(Goal), nl.
display_redo(Goal, Depth):-
true
;
display('Redo: ', Goal, Depth),
fail.
just_do_it(In, Out, Query):-
consult(In),
tell(Out),
call_with_depth_limit(findall(Query, trace(Query), _Solutions), 30, _XMessage),
writeln(_XMessage),
writeln(_Solutions),
told,
unload_file(In),
true.
它工作得很好,除了一件事之外它应该怎么做。当我在函数Query
中的just_do_it(In, Out, Query)
中有变量时,输出带有绑定变量。有没有办法在跟踪的后续步骤中取消绑定变量,这样我就可以看到它何时被绑定?何时没有?
示例输出:
0: Call: a(_G1085,_G1085,_G1087)
0: Exit: a(3,3,7)
0: Redo: a(3,3,7)
1: Call: b(_G1087,_G1085)
1: Exit: b(7,3)
1: Redo: b(7,3)
1: Exit: b(5,1)
1: Redo: b(5,1)
1: Fail: b(_G1087,_G1085)
0: Fail: a(_G1085,_G1085,_G1087)
我希望得到的示例输出:
0: Call: a(_G1085,_G1085,_G1087)
0: Exit: a(3,3,7)
0: Redo: a(_G1085,_G1085,_G1087)
1: Call: b(_G1087,_G1085)
1: Exit: b(7,3)
1: Redo: b(_G1087,_G1085)
1: Exit: b(5,1)
1: Redo: b(_G1087,_G1085)
1: Fail: b(_G1087,_G1085)
0: Fail: a(_G1085,_G1085,_G1087)
答案 0 :(得分:4)
您的口译员有几个问题:
您正在使用不存在的运算符<=
。所以你必须得到一个语法错误。在Prolog中,为了避免与箭头⇐/ =<
混淆,<=
之后的时间越小或越平等。
您正在定义谓词trace/1
,但SWI和许多其他Prolog一样已经预定义了这个谓词。所以最好使用另一个名字。
切割未正确实施。
not/1
的规则应该定义(\+)/1
,并且可以阅读:
trace(\+A, Depth):-!, \+trace(A, Depth).
证明变量应该产生instantiation_error
。就像call(_)
一样。所以你需要作为第一条规则
trace(V, _) :- var(V), !, throw(error(instantiation_error, _)).
要正确显示重做,您需要以更明确的方式替换目标clause(Goal, Body),
。毕竟,除了通过回溯之外,没有办法取消绑定变量。也就是说,我们必须找到变量仍然未实例化的合适时刻。
将clause/2
替换为redo_clause/3
。
redo_clause(Depth, Goal, Body) :-
findall(Goal-Body, clause(Goal, Body), [First|Rest]),
( Goal-Body = First
; length(Rest, RL), length(RestC, RL),
member(Goal-Body,RestC),
display('Redo: ', Goal, Depth),
Rest = RestC
).