0

I'm working with Terms and Signatures (first-order predicate logic) in Prolog.

I've been given the signature (∅, Z, {add(2), sub(2), mult(2)}). So there's no variables, the constants are integers, and the functions are "add", "sub" and "mult".

The goal is to write the predicate "calc/2", which takes a term (given the signature above) and calculates it according the usual definition of addition, subtraction and multiplication of integers. Example:

?- calc( add(sub(8,2), mult(4,-3)), N).
N = -6

(since ((8 − 2) + (4 ∗ −3)) = −6)

The problem is similar and related to this question, but one big difference is that I need to avoid using the =.. operator to find the name of the functions. Instead, I want to take advantage of the fact that Prolog uses pattern matching on a rule's parameters, which is what I'm completely stuck on. Another thing to note is that "add", "sub", and "mult" are not supposed to be predicates.

My first solution using the =.. operator was (with the help of the answer from the thread linked above):

op(+, add).
op(-, sub).
op(*, mult).

calc(Term, N) :-
    calc2(Term, Expr),
    N is Expr.

calc2(N,N) :- integer(N).
calc2(Term, Expr) :-
    Term =.. [Op_str, Comp1, Comp2],
    op(Op, Op_str),
    calc2(Comp1, Expr1),
    calc2(Comp2, Expr2),
    Expr =.. [Op, Expr1, Expr2].

But since this^ isn't the type of solution I'm looking for it doesn't really help much with my issue.

I can pretty easily perform single calculations (like calc(add(1,2), N)), but I struggle with anything more complicated than that.

sitron
  • 3
  • 2

1 Answers1

2

To use pattern matching and avoid the univ operator =.., you can rewrite calc2/2 like this:

calc2(add(Op1, Op2), Expr1 + Expr2) :- 
    calc2(Op1, Expr1),
    calc2(Op2, Expr2).
calc2(sub(Op1, Op2), Expr1 - Expr2) :-
    calc2(Op1, Expr1),
    calc2(Op2, Expr2).
calc2(mult(Op1, Op2), Expr1 * Expr2) :-
    calc2(Op1, Expr1),
    calc2(Op2, Expr2).

This makes the code more visual, where additional cases (e.g. power) can be handled by separate clauses. In addition, modern compilers can optimize the generated code.

peter.cyc
  • 1,763
  • 1
  • 12
  • 19
  • Thank you, such a great answer, it's exactly what I wanted – sitron Oct 29 '20 at 18:28
  • I cannot mark your answer as useful (upvote) since it's the first time I'm using stackoverflow, but I will come back and do so once I've reached 15 reputation. – sitron Oct 29 '20 at 19:09