谓词
nondeterm s(integer,integer)
nondeterm p(integer,integer,integer)
条款
s(V,R) :-
p(0,V,R).
%,write(R),nl.
p(R,0,R).
p(Inc,V,R) :-
I2=Inc+V,
N1=V-1,
p(I2,N1,R).
目标
s(9,O).
给出算术溢出,为什么?
答案 0 :(得分:2)
在Prolog中,数学表达式不是通过赋值完成的,例如=
。 Prolog不像许多常见的编程语言那样使用赋值,Prolog使用统一。如果要在Prolog中进行数学表达式并用变量统一结果,则需要使用is / 2运算符
I2 is Inc+V
N1 is V-1
如果第二个参数为0,您还需要一条保护语句以防止第二个子句被执行。
s(V,O) :-
p(0,V,O).
p(R,0,R).
p(Inc,V,R) :-
V \= 0,
I2 is Inc+V,
N1 is V-1,
p(I2,N1,R).
现在您的查询返回
?- s(9,O).
O = 45 ;
false.
答案 1 :(得分:0)
作为盖伊的答案的补充,在Prolog跟踪器中运行查询非常有帮助,因为它清楚地表明,因为您使用统一(=/2
)而不是算术表达式求值(is/2
),所以查询在每次递归调用时建立一个越来越大的复合项,直到耗尽全局堆栈空间为止:
[trace] ?- s(9,O).
Call: (8) s(9, _3176) ? creep
Call: (9) p(0, 9, _3176) ? creep
Call: (10) _3396=0+9 ? creep
Exit: (10) 0+9=0+9 ? creep
Call: (10) _3402=9-1 ? creep
Exit: (10) 9-1=9-1 ? creep
Call: (10) p(0+9, 9-1, _3176) ? creep
Call: (11) _3408=0+9+(9-1) ? creep
Exit: (11) 0+9+(9-1)=0+9+(9-1) ? creep
Call: (11) _3414=9-1-1 ? creep
Exit: (11) 9-1-1=9-1-1 ? creep
Call: (11) p(0+9+(9-1), 9-1-1, _3176) ? creep
Call: (12) _3420=0+9+(9-1)+(9-1-1) ? creep
Exit: (12) 0+9+(9-1)+(9-1-1)=0+9+(9-1)+(9-1-1) ? creep
Call: (12) _3426=9-1-1-1 ?
...