经过长时间的谷歌搜索,我无法找到一个明确的答案: 在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之后使用它。我这样做的原因是所谓的尝试,看看因为我真的无法理解为什么有时候是在之前,有时是在之后......
答案 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',返回)。