在prolog中反击

时间:2015-09-21 09:08:52

标签: prolog counter

我想在prolog中创建一个计数器。

启动init / 0之类的东西。 添加1个增量/ 0, 和get_counter / 1之类的东西。获得价值。

但是我不知道如果你有没有输入的init / 0如何将东西设置为0,那么如何启动它。

有人可以给我一些提示,我应该怎么做呢?

我不是母语人士,所以如果不清楚我的意思我很抱歉。

3 个答案:

答案 0 :(得分:1)

解决此问题的一种声明方式是将此视为两个计数器值之间的关系:一个在增量之前,一个在增量之后。

您可以使用CLP(FD)约束来关联两个计数器值:

counter_next(C0, C) :- C0 + 1 #= C.

这样的谓词是完全纯粹的,可以在所有方向上使用。

这种关系的序列描述了重复递增计数器,将初始值与其最终状态相关联:

?- S0 = 0, counter_next(S0, S1), counter_next(S1, S).
S = 2,
S0 = 0,
S1 = 1

编辑:假设您采用其他方式并设法实现0-ary谓词increment/0,正如您所要求的那样,破坏性地增加全局资源。然后你会有严重的声明性问题。例如,递增计数器必须成功,因此我们可以看到:

?- increment.
true.

但这意味着原始查询不再等同于自己的答案,因为查询:

?- true.
true.

肯定不会增加柜台。

这也意味着您无法再孤立地测试和推理您的谓词,但必须始终考虑全局资源。

这反过来会使您更难理解和纠正代码中的错误。

因此,我强烈建议您采用声明性方式来考虑此任务,并在增量显式之前和之后建立计数器值之间的关系。作为额外的好处,您还可以在另一个方向上使用这些关系,并询问:“当递增时,哪个初始计数器值(如果有的话)会产生给定值?”,或者更一般地说:“对于哪些参数,这种关系甚至持有?“

答案 1 :(得分:1)

这是你想要实现的目标:

?- X0 = 0 /* init */, succ(X0, X1) /* inc */, succ(X1, X2) /* inc */.
X0 = 0,
X1 = 1,
X2 = 2.

init只是给变量一个值,递增是用succ/2完成的,getval是隐含的。

但是,正如我在评论中已经说过的,考虑你的用例!如果您想要跟踪循环内部的深度,可以使用succ/2或甚至跟suggestion by @mat进行操作。

因此,要计算列表中foo的数量:

list_foos([], 0).
list_foos([X|Xs], N) :-
    (   dif(X, foo)
    ->  list_foos(Xs, N)
    ;   list_foos(Xs, N0),
        succ(N0, N) % or: N0 + 1 #= N
    ).

您应该同时试用succ(N0, N)N0 + 1 #= N,看看如果list_foos/2的一个或两个参数都不存在,您将如何使用它们。

但是,如果由于某种原因需要维护全局状态:例如,您正在动态更改数据库,并且需要为表生成增加的整数键。然后,您应该考虑answer by @coredump。请记住,一旦开始使用“全局”变量,编写在任何Prolog实现上运行的代码并不是一件容易的事。一种尝试是使用predicates for manipulating the database

:- dynamic foocounter/1.

initfoo :-
    retractall(foocounter(_)),
    assertz(foocounter(0)).

incrfoo :-
    foocounter(V0),
    retractall(foocounter(_)),
    succ(V0, V),
    assertz(foocounter(V)).

然后,您现在可以使用全局状态(它不需要像您的示例一样使用):

?- initfoo.
true.

?- incrfoo.
true.

?- incrfoo.
true.

?- foocounter(V).
V = 2.

这是完全有效的代码,但存在许多缺陷,因此请谨慎使用。

答案 2 :(得分:0)

我会使用ECLiPSe's non-local variables

init :- setval(counter, 0).
increment :- incval(counter).
get_counter(V) :- getval(counter, V).

您的实施可能提供类似的东西。在SWI-prolog中,似乎可以使用nb_setval(非可回溯的setval)实现相同的目的。