There are many ways to do this, depending upon the bigger picture of what you're doing and what your goals are. But here is one possibility:
evaluate(cal(X, Op, Y), Result) :-
evaluate(X, Xr),
evaluate(Y, Yr),
Exp =.. [Op, Xr, Yr, Result],
call(Exp).
evaluate(X, X) :- number(X).
plus(X, Y, R) :- R is X + Y.
minus(X, Y, R) :- R is X - Y.
evaluate/2
assumes that you pass it something that looks like a number or a cal/3
where the parameters to cal/3
are an operand, an operator, and another operand, respectively. You write a predicate to evaluate each individual operator, and they assume the operands have been reduced to numbers.
Example:
evaluate(cal(cal(2, plus, 3), minus, 8), Result).
Gives:
Result = -3.
In the stated example:
| ?- calculations(Tree,[1,+,2,-,3],[]), evaluate(Tree, Result).
Result = 0
Tree = cal(cal(1,plus,2),minus,3) ? a
no