我一直在寻找关于累加器是什么以及它们做什么的教程,但是所有的解释似乎都非常复杂,并没有真正给我一个清晰的图片说明它们如何工作以便我可以使用它的。我似乎明白累加器会保留一些数字,然后可以被其他代码调用并更改。问题是虽然我理解累加器是什么并知道什么时候需要它,我不太确定如何实际使用它。
我的意思是从我见过的教程中,有时累加器似乎是一个空列表,而有时它似乎是'0'让我想知道究竟什么可以被认为是累加器而什么不能。有人可以用简单的语言向我解释一下如何使用累加器吗?
同样对于我的问题的第二部分,我似乎注意到人们在他们的prolog代码中使用了很多:
\+member
我设法推断它与列表有关,因为我总是看到它在一行代码中使用,但是在搜索后我发现+成员实际上意味着什么是“否定为失败 - 不可证明“虽然我不明白这意味着什么,或者即使那个人是正确的。再说一次,有人可以向我解释一下+成员究竟做了什么以及它可以用于什么,同时试图让你的解释变得简单,大词让我迷惑xD。
非常感谢你对这两件事的任何帮助。
答案 0 :(得分:8)
首先,\+
是对目标的否定。当它的目标失败时,它会成功。例如:
?- member(3, [1,2,3]). # 3 is a member of the List
true.
?- member(4, [1,2,3]). # 4 is not a member
false.
?- \+member(4, [1,2,3]). # succeeds, because 'member' fails
true.
?- \+member(3, [1,2,3]).
false.
?- atom_chars('hi', C).
C = [h, i].
?- atom_chars('hi', [h, i]).
true.
?- atom_chars('hello', [h, i]).
false.
?- \+atom_chars('hello', [h, i]).
true.
其次,累加器是一种通过递归线程化状态的方法,以利用尾递归优化。
考虑这两种计算阶乘的等价方法:
?- [user].
|: fact_simple(0, 1).
|: fact_simple(N, F) :-
N1 is N-1,
fact_simple(N1, F1),
F is N*F1.
|: % user://2 compiled 0.00 sec, 440 bytes
true.
?- fact_simple(6, F).
F = 720 .
[user].
|: fact_acc(N, F) :- fact_acc(N, 1, F).
|: fact_acc(0, Acc, Acc).
|: fact_acc(N, Acc0, F) :-
N1 is N-1,
Acc is Acc0 * N,
fact_acc(N1, Acc, F).
|: % user://4 compiled 0.00 sec, 1,912 bytes
true.
?- fact_acc(6, F).
F = 720 .
第一个版本在递归中调用自身,等待子查询完成。只有这样它才能将N
- 值乘以子句的结果。
第二个版本使用累加器(Acc
)。请注意1
不是累加器,而是初始值。之后,对谓词的每次调用都将它的N
- 值与累加器相乘,并且当递归到达它的基本情况时,累加器的值已经是最终值。
问题实际上不是'累加器能做什么? (0或空列表或任何东西)。它只是一种累积值的方式,而且永远不会返回到调用谓词。这样,Prolog系统就不必构建一个不断增长的调用堆栈。
但请注意,在此示例中,乘法的顺序自然会相反。乘法并不重要,但对于其他值(如列表),必须要考虑到这一点。
fact_simple
将乘法设为1 * 2 * 3 * 4 * 5 * 6
,而fact_acc
设为1 * 6 * 5 * 4 * 3 * 2
。如果这还不清楚,那就去做一下这两个!