prolog - 为什么这个奇怪的痕迹

时间:2009-11-19 12:39:52

标签: logic prolog

这里是prolog代码(我跟着它)。

len([],0).
len([_|T],N) :- len(T,X), N is X+1.

以下是它的跟踪(即运行linux,swi)

    [trace]  ?- len([d,f,w,c],X).
   Call: (7) len([d, f, w, c], _G314) ? 
   Call: (8) len([f, w, c], _L182) ? 
   Call: (9) len([w, c], _L201) ? 
   Call: (10) len([c], _L220) ? 
   Call: (11) len([], _L239) ? 
   Exit: (11) len([], 0) ? 
^  Call: (11) _L220 is 0+1 ? 
^  Exit: (11) 1 is 0+1 ? 
   Exit: (10) len([c], 1) ? 
^  Call: (10) _L201 is 1+1 ? 
^  Exit: (10) 2 is 1+1 ? 
   Exit: (9) len([w, c], 2) ? 
^  Call: (9) _L182 is 2+1 ? 
^  Exit: (9) 3 is 2+1 ? 
   Exit: (8) len([f, w, c], 3) ? 
^  Call: (8) _G314 is 3+1 ? 
^  Exit: (8) 4 is 3+1 ? 
   Exit: (7) len([d, f, w, c], 4) ? 
X = 4.

我知道prolog会运行这些'树',但我很难弄清楚为什么变量的增量仅在它退出时才会完成 - 对此机制的任何解释?

非常感谢!

1 个答案:

答案 0 :(得分:6)

原因是N is X+1是谓词的最后一部分。

这样想:要计算N is X+1,我们需要知道X的值,这是通过调用len(T,X)来计算的。但是,计算X的过程需要再次调用len,一直到最终会出现空列表的情况。

此时列表长度已知,即0.因此该值为“返回”。只有这样0 + 1才能计算并“返回”。然后是1 + 1.等等。

以另一种方式思考,观察对于任何两个谓词aba, b如果同时a和{{0}}都会生成true {1}}是真的。在Prolog中,b只有在知道b为真时才会被评估(否则评估a没有意义,因为结果已知为假)。

因此,所有添加都是在递归调用b之后完成的。