我正在尝试评估算术二叉树。
tree_calc(tree(L, Root, R), Eval) :- compute(Root, L, R, Eval).
compute(Root, 'empty', 'empty', Root).
compute(Root, L, R, Eval):- number(L), number(R), E =..[Root,L,R], Eval is E.
compute(Root, L, R, Eval):-
L = tree(LL, LRoot, LR), R = tree(RL, RRoot, RR),
E =..[Root, compute(LRoot, LL, LR, LEval), compute(RRoot, RL, RR, REval)],
Eval is E.
当我使用输入运行程序时:
tree_calc(tree(tree(empty,2,empty),
'+',tree(tree(empty,1,empty),
'/',tree(empty,2,empty))), Eval).
我收到错误:
ERROR: is/2: Arithmetic: `compute/4' is not a function
我似乎无法弄清楚为什么会抛出这个错误,因为我认为只有在未定义函数时才会显示此错误。
感谢您的帮助。
答案 0 :(得分:1)
虽然Scott解决了您遇到的最棘手的技术问题,但您可能有兴趣了解更简单,声明性的方法:
tree_calc(tree(L, +, R), Eval) :- tree_calc(L, Lr), tree_calc(R, Rr), Eval is Lr+Rr.
tree_calc(tree(L, /, R), Eval) :- tree_calc(L, Lr), tree_calc(R, Rr), Eval is Lr/Rr.
tree_calc(tree(empty, N, empty), N).
这在关于树的正确性的一些限制性假设下工作(例如,叶子是数字,并且仅使用指定的运算符):
?- tree_calc(tree(tree(empty,2,empty),
'+',tree(tree(empty,1,empty),
'/',tree(empty,2,empty))), Eval).
Eval = 2.5 ;
false.
另一种方法,因为/ 2实际上是对表达式树进行求值,可能是
tree_calc(T, V) :- translate(T, E), V is E.
translate(tree(empty,N,empty), N) :- !.
translate(tree(L,Op,R), E) :-
E =.. [Op,Lt,Rt],
translate(L, Lt),
translate(R, Rt).
现在可以使用所有Prolog(二进制)算术运算符。切换是为了避免在回溯时尝试在原子上调用univ / 2 ...
答案 1 :(得分:0)
is
用于算术分配,不用于统一。 (例如,A=1+1
不会以A
为2结束,但A is 1+1
会结束。)因此,Prolog正在尝试对右边的表达式进行算术计算,其中包含看似算术的表达式功能,但显然不是。
您可以使用=
代替is
,或者更简洁地消除E
,并直接与Eval
统一:Eval =..[Root, compute(
...
然后,您似乎正在使用compute
返回列表中的某些内容,因此Prolog可能不是唯一一个感到困惑的人。