I wanted to write evaluating predicate in Prolog for arithmetics and I found this:
eval(A+B,CV):-eval(A,AV),eval(B,BV),CV is AV+BV.
eval(A-B,CV):-eval(A,AV),
Your almost DRY solution does not work for several reasons:
Formula =.. [Op, L, R]
refers to binary operators only. You certainly want to refer to numbers too.
The arguments L
and R
are not considered at all.
Op(L,R)
is not valid Prolog syntax.
on the plus side, your attempt produces a clean instantiation error for a variable, whereas positive/1
would fail and eval/2
loops which is at least better than failing.
Since your operators are practically identical to those used by (is)/2
you might want to check first and only then reuse (is)/2
.
eval2(E, R) :-
isexpr(E),
R is E.
isexpr(BinOp) :-
BinOp =.. [F,L,R],
admissibleop(F),
isexpr(L),
isexpr(R).
isexpr(N) :-
number(N).
admissibleop(*).
admissibleop(+).
% admissibleop(/).
admissibleop(-).
Note that number/1
fails for a variable - which leads to many erroneous programs. A safe alternative would be
t_number(N) :-
functor(N,_,0),
number(N).