2

这是序言代码(我有点遵循)。

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.

我知道序言会沿着这些“树”运行,但我无法弄清楚为什么变量的增量仅在它退出时才完成 - 对此机制的任何解释?

非常感谢!

4

1 回答 1

6

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

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

正是在这一点上,列表长度是已知的,即 0。因此该值被“返回”。只有这样 0 + 1 才能计算并“返回”。然后是 1 + 1。等等。

换一种方式考虑,观察到对于任何两个谓词aand b,当且a, b两者都为真时产生真。在 Prolog 中,只有在已知为真时才会评估(否则评估没有意义,因为已知结果为假)。abbab

因此,所有添加都递归调用之后完成len

于 2009-11-19T12:45:14.657 回答