I have these 3 predicates:
times(X, Y):-
Result is X * Y.
minus(X, Y):-
Result is X - Y.
plus(X, Y):-
Result is X + Y.
and I want to pass for example times(2,2) in the plus(X, Y) like this plus(times(2,2), minus(X, Y)).
The relationship between the title of your question and the text of your question is unclear to me, and I think @false is probably right that there is a more fundamental misunderstanding about Prolog here. I don't know if this really addresses your need or not, but the alternative here is writing your own evaluator.
eval(times(X,Y), Result) :-
eval(X, XResult),
eval(Y, YResult),
Result is XResult * YResult.
eval(minus(X,Y), Result) :-
eval(X, XResult),
eval(Y, YResult),
Result is XResult - YResult.
eval(plus(X,Y), Result) :-
eval(X, XResult),
eval(Y, YResult),
Result is XResult + YResult.
The recursive calls to eval/2 inside the bodies of each of these rules are needed to handle cases like plus(times(2,2), minus(X, Y)). Then you need a rule for numbers:
eval(Num, Num) :- number(Num).
This works great for cases like this:
?- eval(plus(times(2,2), minus(7,1)), Result).
Result = 10.
It doesn't do you any good for cases like this:
?- eval(plus(times(2,2), minus(X,Y)), Result).
ERROR: Out of local stack
Of course, it would work if we established bindings for X and Y before getting there, but if you want it to generate possible solutions for X and Y you're out of luck, you'll need to use clpfd. The reason for this curious error, if you trace in, is because number(X) when X is unbound is false, so it is actually generating new clauses involving the times, minus and plus structures and trying them, which isn't what you want in an evaluator.
Edit: implementing printterm/1.
The eval/2 predicate shows you how to perform a recursive tree walk. The principal is the same with making a pretty printer. I am very lazy so I will only sketch it, you'll have to fill in the details yourself.
printterm(T) :- format_term(T, Formatted), write(Formatted), nl.
format_term(plus(X,Y), Formatted) :-
format_term(X, XFormatted),
format_term(Y, YFormatted),
format(atom(Formatted), '(~a + ~a)', [XFormatted, YFormatted]).
% other format_term clauses here for other arithmetic expressions
format_term(X, X) :- number(X).
Hope this helps!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With