递归搜索&蓄电池& Prolog的计数器

时间:2017-02-12 17:36:25

标签: recursion prolog counter accumulator

经过长时间的谷歌搜索,我无法找到一个明确的答案: 在Prolog中自己做递归很容易。我的主要问题是了解放置累加器和计数器的位置。这是一个例子:

char a[]=" 0xa this is a343 good";
char* p;   // Notice: just one * as you need a pointer to char
long int b=0;
b=strtol(a, &p,0);
            ^^
            Notice: & (aka address of). So you pass the address of 
                    a pointer to char. Equivalent to char** as expected
                    by strtol

在第一个例子中,我在递归前使用了一个计数器,但在第二个例子中,我在AFTER之后使用它。我这样做的原因是所谓的尝试,看看因为我真的无法理解为什么有时候是在之前,有时是在之后......

3 个答案:

答案 0 :(得分:3)

update:最重要的是,如果递归调用不是最后一个,则谓词不是尾递归的。因此,如果可能的话,应该避免在递归调用之后有任何事情。请注意the answer user false 中的两个定义都是尾递归的,这恰恰是由于算术条件之前的递归调用,两者都有。这是非常基本的,我们必须努力明确地注意它。

有时我们会倒计时,有时我们会数数。我在another answer详细讨论了这个问题。它讨论了累加器,前后。 :)

还有一个叫做“关联性”的操作(比如+),其中

a+(b+(c+....)) == (a+b)+(c+...)

让我们重新组合和(部分)计算得更快而不是更晚。尽快,但不会更快。

答案 1 :(得分:3)

简短的回答:你可以在之前和之后放置这样的算术关系两者。至少,如果您使用约束来代替(is)/2。唯一的区别可能是终止和错误。

因此,让我们看看如何使用约束来定义谓词:

:- use_module(library(clpfd)).

nXList(0,_,[]).
nXList(N,X,[X|T]):-
    N #> 0,
    N1 #= N-1,
    nXList(N1,X,T).

media([], 0, 0).
media([X|L], N, Soma):-
   N #> 0,
   N #= N1 + 1,
   Soma #= Soma1 + X,
   media(L, N1, Soma1).

您现在可以更通用的方式使用这些定义,例如:

?- nXList(3, X, T).
T = [X, X, X] ;
false.

?- media(Xs, 3, S).
Xs = [_A, _B, _C],
_D+_A#=S,
_C+_B#=_D ;
false.

... nXList/3可以通过以下方式更紧凑地表达:

..., length(T, N), maplist(=(X), T), ...

答案 2 :(得分:3)

也许问题的中心点在序言中:

  

在Prolog中自己做递归很简单

我们没有循环,因为我们没有办法控制它们。变量分配一次

所以,我认为实际的答案很简单:如果'谓词' (比如是/ 2)需要一个变量值,在调用它之前将变量置于基础之上。

对我来说,将Prolog程序(一组子句)视为语法产生,将子句参数视为属性,或者继承(在'指令指针之前计算的值)或合成(值)是有帮助的计算' here',返回)。