这里是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会运行这些'树',但我很难弄清楚为什么变量的增量仅在它退出时才会完成 - 对此机制的任何解释?
非常感谢!
答案 0 :(得分:6)
原因是N is X+1
是谓词的最后一部分。
这样想:要计算N is X+1
,我们需要知道X
的值,这是通过调用len(T,X)
来计算的。但是,计算X
的过程需要再次调用len
,一直到最终会出现空列表的情况。
此时列表长度已知,即0.因此该值为“返回”。只有这样0 + 1才能计算并“返回”。然后是1 + 1.等等。
以另一种方式思考,观察对于任何两个谓词a
和b
,a, b
如果同时a
和{{0}}都会生成true {1}}是真的。在Prolog中,b
只有在知道b
为真时才会被评估(否则评估a
没有意义,因为结果已知为假)。
因此,所有添加都是在递归调用b
之后完成的。