假设我调用查询member(a, [c,b,a,y])
,输出为-
true ;
false.
我们为什么会有“另一种解决方案”?为什么我们不能在true.
结束?
这是痕迹:
%% [trace] ?- member(a,[c,b,a,y]).
%% Call: (6) member(a, [c, b, a, y]) ?
%% Call: (7) member(a, [b, a, y]) ?
%% Call: (8) member(a, [a, y]) ?
%% Exit: (8) member(a, [a, y]) ?
%% Exit: (7) member(a, [b, a, y]) ?
%% Exit: (6) member(a, [c, b, a, y]) ?
%% true ;
%% Redo: (8) member(a, [a, y]) ?
%% Call: (9) member(a, [y]) ?
%% Call: (10) member(a, []) ?
%% Fail: (10) member(a, []) ?
%% Fail: (9) member(a, [y]) ?
%% Fail: (8) member(a, [a, y]) ?
%% Fail: (7) member(a, [b, a, y]) ?
%% Fail: (6) member(a, [c, b, a, y]) ?
%% false.
我不明白我们如何回溯到(8),为什么?
member(X,[X|_]).
member(X,[Y|T]) :- member(X,T).
答案 0 :(得分:4)
让我们将其重写为几乎等效的单线纸
membr(X,[A|B]):- ( X = A ; membr(X,B) ).
追踪它可能会更清楚:
[trace] 5 ?- trace, membr(a, [c,b,a,y]). X=a
Call: (8) membr(a, [c, b, a, y]) ? creep [A8|B8]=[c,b,a,y]
Call: (9) a=c ? creep X=A8 ?
Fail: (9) a=c ? creep false
Redo: (8) membr(a, [c, b, a, y]) ? creep membr(X,B8) ?
Call: (9) membr(a, [b, a, y]) ? creep [A9|B9]=B8
Call: (10) a=b ? creep X=A9 ?
Fail: (10) a=b ? creep false
Redo: (9) membr(a, [b, a, y]) ? creep membr(X,B9) ?
Call: (10) membr(a, [a, y]) ? creep [A10|B10]=B9
Call: (11) a=a ? creep X=A10 ?
Exit: (11) a=a ? creep true
Exit: (10) membr(a, [a, y]) ? creep success!
Exit: (9) membr(a, [b, a, y]) ? creep success!
Exit: (8) membr(a, [c, b, a, y]) ? creep success!
true ;
Redo: (10) membr(a, [a, y]) ? creep membr(X,B10) ?
Call: (11) membr(a, [y]) ? creep [A11|B11]=B10
Call: (12) a=y ? creep X=A11 ?
Fail: (12) a=y ? creep .........
Redo: (11) membr(a, [y]) ? creep .........
Call: (12) membr(a, []) ? creep
Fail: (12) membr(a, []) ? creep
Fail: (11) membr(a, [y]) ? creep
Fail: (10) membr(a, [a, y]) ? creep
Fail: (9) membr(a, [b, a, y]) ? creep
Fail: (8) membr(a, [c, b, a, y]) ? creep
false.
在达到第一个成功之后,显然有一个选择点正在等待:
(10) membr(X,[A|B]):- ( X = A ; membr(X,B) ).
报告成功后,所有帧仍保留在堆栈中,从成功停止的那一刻起重试最上面的第10帧:
(10) membr(X,[A|B]):- ( X = A ; membr(X,B) ).
出口链是临时的:我们只追溯了堆栈以报告发现的值,因为它的点和点存储在导致第11帧成功的帧中({ 1}})。这些框架并没有消除,因为如果有的话,我们将只能报告第一个发现的值。但是Prolog希望报告其中的所有 。