当你给某物起个名字时,它突然变得比以前更真实了。现在可以通过简单地使用概念名称来讨论某些事情。没有更多的哲学,不,累加器没有什么特别之处,但它们很有用。
在实践中,通过一个没有累加器的列表:
foo([]).
foo([H|T]) :-
foo(T).
列表的头部被留下,不能被递归调用访问。在每个递归级别,您只能看到列表的剩余部分。
使用累加器:
bar([], _Acc).
bar([H|T], Acc) :-
bar(T, [H|Acc]).
在每个递归步骤中,您都有剩余的列表和您经历过的所有元素。在您的len/3
示例中,您只保留计数,而不是实际元素,因为这就是您所需要的。
一些谓词(如len/3
)可以使用累加器进行尾递归:您无需等待输入结束(用尽列表的所有元素)来完成实际工作,而是在获得输入时增量执行. Prolog 不必将值留在堆栈上,并且可以为您进行尾调用优化。
需要知道“到目前为止的路径”的搜索算法(或任何需要具有状态的算法)使用相同技术的更通用形式,通过为递归调用提供“中间结果”。例如,一个行程编码器可以定义为:
rle([], []).
rle([First|Rest],Encoded):-
rle_1(Rest, First, 1, Encoded).
rle_1([], Last, N, [Last-N]).
rle_1([H|T], Prev, N, Encoded) :-
( dif(H, Prev)
-> Encoded = [Prev-N|Rest],
rle_1(T, H, 1, Rest)
; succ(N, N1),
rle_1(T, H, N1, Encoded)
).
希望有帮助。