第二条规则基本上说F是N的阶乘如果N大于零并且有一个数字N1是N-1 和的结果F1是N1的阶乘和 F是N和F1的乘积。
示例
假设你想找到 3 的阶乘。
-? factorial(3,F).
Prolog 将factorial(3,F) 放在目标堆栈中,然后查找与第一个目标匹配的规则。 factorial/2 有两条规则(factorial(0,1) 可以看作是一条没有body 的规则),但是对于第一个0 和5 不统一所以不能使用。第二个与 N 被实例化为 5 相结合,Prolog 将条件添加到堆栈中,变为:
3 > 0, N1 is 3-1, factorial(N1,F1), F is 3*F1
第一个目标得到满足,因为 3 大于零。第二个是通过将N1 绑定到3-1 的算术评估结果来满足的,因此现在的目标堆栈是:
factorial(2,F1), F is 3*F1
再次,Prolog 寻找可能用于满足 factorial(2,F1) 的规则并使用第二个规则(N 与 2 统一,F 与 F1 统一,变量使用不同的名称):
2 > 0, N2 is 2-1, factorial(N2,F2), F1 is 2*F2, F is 3*F1
接下来,2 > 0 为真,N2 与2-1 的算术结果统一,因此目标堆栈变为:
factorial(1,F2), F1 is 2*F2, F is 3*F1
对factorial/2再次使用第二条规则:
1 > 0, N3 is 1-1, factorial(N3,F3), F2 is 1*F3, F1 is 2*F2, F is 3*F1
N3 变为零(满足N3 is 1-1 时):
factorial(0,F3), F2 is 1 * F3, F1 is 2*F2, F is 3*F1
此时,factorial/2 的第一条规则可以用来满足factorial(0, F3),但是由于可以使用的规则更多,所以创建了一个选择点。因此,factorial(0,F3) 通过将F3 实例化为 1 成功。
F2 is 1 * 1, F1 is 2 * F2, F is 3 * F3
通过满足堆栈中剩余的所有目标,F 变为 6,您将获得第一个解决方案。但是,factorial(0, F3) 有一个选择点。此时可以使用第二条规则:
0>0, N4 is 0-1, factorial(N4,F4), F3 is 0*F4, F2 is 1*F3, F1 is 2*F2, F is 3*F3
但是0>0 失败并且执行停止,因为没有其他选择指向回溯。
您可以通过使用 [green] 剪切运算符来避免为 factorial(0,_) 留下无用的选择点。
factorial(0, 1) :- !.