given a signature (0,Z,{plus(2),minus(2),times(2)}
, constants are integers and functions are plus, minus and times with arity 2
for each. I wanted to write a two predicates arth/2
and printarth/1
which takes terms in the above signature and do the necessary arithmetic calculations addition, subtraction and multiplication.arth/2
will print the results and printarth/1
should results out the evaluation expression as shown below.
I wanted to achieve two things
first:
?- arth( plus(minus(8,2), times(4,-3)), N).
N = -6
N is evaluated as ((8−2) + (4∗−3)) = (6 +−12) =−6
second:
?- printarth(plus(minus(8,2), times(4,-3)), N).
((8 - 2) + (4 * -3))
true.
I understand that the use of Terms, Ops and complex terms
are used for this and started my code as below
arithmetic_operator('+').
arithmetic_operator('-').
arithmetic_operator('*').
arithmetic_expression(N) :- integer(N).
arithmetic_expression(Term) :-
Term =..[Functor,Component1,Component2],
arithmetic_operator(Functor),
arithmetic_expression(Component1),
arithmetic_expression(Component2).
From here I find it difficult on how to create arth/2
and printarth/1
as I cannot call arithmetic_expression(Term)
and throws me an error when I call it.
?- arithmetic_expression(..[+,5,7]).
ERROR: Syntax error: Operator expected
ERROR: arithmetic_expression(.
ERROR: ** here **
ERROR: .[+,5,7]) .
any resources on this task is very useful.
If you want to take a term that looks like this:
minus(2, 3)
and turn it into an arithmetic expression -(2, 3)
which is equivalent to 2 - 3
(with the default definition of -
as an operator), then evaluate it, you could do it like this:
term_arithmetic_expression(T, E) :-
T =.. [Name, X, Y],
binary_op(Name, Op),
E =.. [Op, X, Y].
eval_arithmetic_expression(T, R) :-
term_arithmetic_expression(T, E),
R is E.
binary_op(minus, -).
% add more binary operations
Now this at least works:
?- eval_arithmetic_expression(minus(2, 3), R).
R = -1.
As you see, both term_arithmetic_expression/2
and eval_arithmetic_expression/2
have two arguments. This is what you need to map minus(2, 4)
to 2 - 4
.
Your arithmetic_expression/1
is correctly traversing, but not mapping from the one representation to the other. Your arithmetic_operator
has the same problem. With minimal changes:
arithmetic_operator(plus, +).
arithmetic_operator(minus, -).
arithmetic_operator(times, *).
arithmetic_expression(N, N) :- integer(N).
arithmetic_expression(Term, Expr) :-
Term =.. [Functor,Component1,Component2],
arithmetic_operator(Functor, Operator),
arithmetic_expression(Component1, Expr1),
arithmetic_expression(Component2, Expr2),
Expr =.. [Operator, Expr1, Expr2].
and then:
?- arithmetic_expression(plus(minus(8,2), times(4,-3)), Expr).
Expr = 8-2+4* -3 ;
false.
?- arithmetic_expression(plus(minus(8,2), times(4,-3)), Expr),
Result is Expr.
Expr = 8-2+4* -3,
Result = -6 ;
false.
?- arithmetic_expression(plus(minus(8,2), times(4,-3)), Expr),
Result is Expr,
display(Expr).
+(-(8,2),*(4,-3))
Expr = 8-2+4* -3,
Result = -6 ;
false.
The display
is what is outputting +(-(8,2),*(4,-3))
in the last query.