打印出一些状态:
sum(J, K, N) :- sum_iter(J, K, N, J, 0).
% the rule at the end of the recursion
sum_iter(J, K, N, I, S) :-
format("rule 1: J=~w K=~w N=~w I=~w S=~w\n", [J, K, N, I, S]),
Kn is K+1,
I = Kn,
format("...pos 1 passed\n"),
N = S,
format("...pos 2 passed\n"),
!.
% the rule perfoming the recursion
sum_iter(J, K, N, I, S) :-
format("rule 2: J=~w K=~w N=~w I=~w S=~w\n", [J, K, N, I, S]),
I =< K,
format("...pos 3 passed\n"),
NewI is I+1,
NewS is S+I,
sum_iter(J, K, N, NewI, NewS).
?- sum(1,3,What).
rule 1: J=1 K=3 N=_11338 I=1 S=0
rule 2: J=1 K=3 N=_11338 I=1 S=0
...pos 3 passed
rule 1: J=1 K=3 N=_11338 I=2 S=1
rule 2: J=1 K=3 N=_11338 I=2 S=1
...pos 3 passed
rule 1: J=1 K=3 N=_11338 I=3 S=3
rule 2: J=1 K=3 N=_11338 I=3 S=3
...pos 3 passed
rule 1: J=1 K=3 N=_11338 I=4 S=6
...pos 1 passed
...pos 2 passed
What = 6.
最后,I = Kn 变成了一个测试:I 和 Kn 都是
设置为实际值,I 一个“结束”。
你可以这样做,使用 I > K "guard":
sum_iter(_, K, Res, I, Res) :- I > K,!.
但你也想这样做:
- 如果适用,默认调用递归规则。
- 如果不是,调用“递归结束规则”。
所以重新排列是最好的:
sum(J, K, N) :- sum_iter(J, K, N, J, 0).
% the rule perfoming the recursion, with a guard "I =< K", which, once
% successful, commits the computation to this one rule, so we add "!"
sum_iter(J, K, N, I, S) :-
format("rule 2: J=~w K=~w N=~w I=~w S=~w\n", [J, K, N, I, S]),
I =< K,!,
format("...pos 3 passed\n"),
NewI is I+1,
NewS is S+I,
sum_iter(J, K, N, NewI, NewS).
% the rule at the end of the recursion, also with guard:
sum_iter(J, K, Res, I, Res) :-
format("end: J=~w K=~w I=~w Res=~w\n", [J, K, I, Res]),
I > K,!.
其实第二个中的“cut”是没有必要的
规则,因为它是最后一条规则。没有必要
守卫在这种情况下,这只是守卫的否定
第一条规则。但为了清楚起见,让我们将两者都保留。
?- sum(1,3,What).
rule 2: J=1 K=3 N=_15630 I=1 S=0
...pos 3 passed
rule 2: J=1 K=3 N=_15630 I=2 S=1
...pos 3 passed
rule 2: J=1 K=3 N=_15630 I=3 S=3
...pos 3 passed
rule 2: J=1 K=3 N=_15630 I=4 S=6
end: J=1 K=3 I=4 Res=6
What = 6.