问题
This question is directly related to first order logic creating terms for arithmetic expressions using prolog. After implementing the logic as per the link I have issues with the formatting of the ourput for printauth/1
. It currently results as 8-2+4* -3
, how is it possible to get something like ((8-2)+(4* -3))
(notice its not the same as +(-(8,2),*(4,-3)))
.
I have been trying to using various options (\k,\q) in format/2
predicate but nothing works. even I tried write_canonical
and other write predicates, still no success.
printterm(Term) :- arithmetic_expression(Term, Expr), format("(~q)\n", [Expr]).
%write_canonical(Expr).
%write_term(Expr, [ignore_ops(true)]).
%format("(~q)\n", [Expr]) .
current output:
?- printterm(plus((minus(8,2)),(times(4,3)))).
(8-2+4*3)
true .
expected output:
?- printterm(plus((minus(8,2)),(times(4,3)))).
((8-2)+(4*3))
true .
Is it possible to achieve this?
回答1:
The term you passed to your printterm
:
plus((minus(8,2)),(times(4,3)))
This is conventionally written as:
plus(minus(8, 2), times(4, 3))
The parentheses are not needed and are indeed lost when the term is read. Try:
?- X = plus((minus(8,2)),(times(4,3))).
To get what you want it seems you really need to program it. For example:
print_arithmetic_expression(E) :-
phrase(parenthesized_expression(E), P),
format("~s~n", [P]).
parenthesized_expression(E) -->
atomic_expr(E),
!.
parenthesized_expression(E) -->
{ expr_op(E, Op, A, B) },
pexp(A),
" ", [Op], " ",
pexp(B).
atomic_expr(E) -->
{ atomic(E),
format(codes(C), "~w", [E])
},
C.
expr_op(plus(A,B), 0'+, A, B).
expr_op(minus(A,B), 0'-, A, B).
expr_op(times(A,B), 0'*, A, B).
pexp(E) -->
atomic_expr(E),
!.
pexp(E) -->
{ expr_op(E, Op, A, B) },
"(",
pexp(A),
" ", [Op], " ",
pexp(B),
")".
I get:
?- print_arithmetic_expression(plus(minus(8, 2), times(4, 3))).
(8 - 2) + (4 * 3)
true.
回答2:
Why not roll your own printing predicate?
Make it return a String for added flexibility (so you are free to decide whether to pump the String out to the real world immediately, or manipulate it further first).
Something like this for all operations:
printterm(plus(S1,S2),R) :-
printterm(S1,RS1),
printterm(S2,RS2),
atomic_list_concat(['(',RS1,'+',RS2,')'],R).
printterm(minus(S1,S2),R) :- ...
printterm(times(S1,S2),R) :- ...
Then to use it, call it from printterm/1
printterm(Term) :-
arithmetic_expression(Term, Expr),
printterm(Expr,R),
format("~w\n", [R]).
来源:https://stackoverflow.com/questions/64369051/formatting-the-output-with-proper-paranthesis-prolog