Q:

Defining the rule to avoid Arithmetic Error is/2 in Prolog

I'm trying to implement a binary tree in Prolog and I'm getting the following error:
ERROR: is/2: Arithmetic: `z/0' is not a function

I understand that this error occurs because the RHS of is/2 has not been instantiated properly.
But I'm finding it difficult to figure out how to instantiate my variable z in the second tree_eval/3 .
tree_eval(_,tree(empty,Num,empty),Num).
tree_eval(Value,tree(empty,z,empty),Value):-
        z = Value.
tree_eval(Value,tree(L,Op,R),Eval):-
        tree_eval(Value,L,LEval),
        tree_eval(Value,R,REval),
        eval(LEval,REval,Op,Eval).

eval(LEval,REval,Op,Result):-
        Op = '+',
        Result is LEval + REval.
eval(LEval,REval,Op,Result):-
        Op = '-',
        Result is LEval - REval.
eval(LEval,REval,Op,Result):-
        Op ='/',
        Result is LEval/REval.

How do I assign Value to z here?
Thanks in advance.

A:

By z=Value you are actually unifying the variable Value with the atom z. If you mean z to be a variable you have to write it as a capital letter Z as @vmg pointed out:
tree_eval(Value,tree(empty,Z,empty),Value):-
        Z = Value.

In that case it is interesting to consider what happens when querying the predicate:
   ?- tree_eval(V,tree(empty,3,empty),E).
E = 3 ? ;
E = V = 3 ? ;
no

The first solution is produced by your first rule in which you have an anonymous variable for the first argument. The second solution is produced by your second rule in which you demand the first and third arguments to be the same. So essentially you have two derivation paths for the value that is 3 in both cases. Now let's look at a slightly bigger tree:
?- tree_eval(V,tree(tree(empty,2,empty),+,tree(empty,3,empty)),E).
E = 5 ? ;
E = 5,
V = 3 ? ;
E = 5,
V = 2 ? ;
no

The first answer is hardly suprising as the tree evaluates to 5 indeed but what about the next two solutions? Let's take a look how prolog comes to these solutions: The term
tree(tree(empty,2,empty),+,tree(empty,3,empty))

matches only with the third rule because the subtrees are not empty. So tree_eval/3 is called with the subtree tree(empty,2,empty) and yields as first solution: (_,tree(empty,2,empty),2)
Then tree_eval/3 is called for the subtree tree(empty,3,empty) with the first solution: (_,tree(empty,3,empty),3)
Now eval(2,3,+,Eval) yields Eval=5. The first argument however is still Value=_. So the first solution for the query is: E=5.
If you ask for other answers prolog will try if there are further solutions for the 3rd goal, determine there are none, hence backtracking to the 2nd goal: the right subtree, and indeed your second rule delivers: (3,tree(empty,3,empty),3). eval(2,3,+,Eval) again contributes Eval=5, hence the second solution to the query: E=5, V=3.
If you still ask for more solutions prolog has to backtrack further to the 1st goal: and your 2nd rule delivers again: (2,tree(empty,2,empty),2). Now your second goal again matches the 1st rule: (_,tree(empty,3,empty),3), eval/4 delivers again Eval=5, so the 3rd solution to the query is: E=5, V=2
Backtracking one more time to goal 2 prolog is trying the 2nd rule again and fails because the first argument can't be 2 and 3 at the same time. So there is no 4th solution to the query.
However, if tree_eval/3 would be queried with the same tree structure but both leaves being 2 it is, by the above reasoning, not really suprising that there are 4 solutions:
   ?- tree_eval(V,tree(tree(empty,2,empty),+,tree(empty,2,empty)),E).
E = 4 ? ;
E = 4,
V = 2 ? ;
E = 4,
V = 2 ? ;
E = 4,
V = 2 ? ;
no

Looking at those multiple solutions it is apparent that your third argument is delivering the correct solution, and that you don't really need the first argument. You can also do without the second rule. Incorporating some improvements suggested by @mat, your predicate might then look something like that:
tree_evaluation(tree(empty,Num,empty),Num).
tree_evaluation(tree(L,Op,R),Val) :-
    tree_evaluation(L,LVal),
    tree_evaluation(R,RVal),
    evaluation(LVal,RVal,Op,Val).

evaluation(L,R,+,V) :-
    V is L + R.
evaluation(L,R,-,V) :-
    V is L - R.
evaluation(L,R,/,V) :-
    V is L / R.

This version yields unique answers:
    ?- tree_evaluation(tree(empty,3,empty),E).
E = 3 ? ;
no

     ?- tree_evaluation(tree(tree(empty,2,empty),+,tree(empty,3,empty)),E).
E = 5 ? ;
no

