Is it possible to use the prolog format
predicate to print to file?
I have a table of data that I print to stdout using the format predicate, i.e.
print_table :-
print_table_header,
forall(range(1.0,10.0,0.1,N), print_row(N,L)).
%% print_row(L) :- take a list of the form, [a,b,c,d,e] and
%% print it to screen as a single row of tab separated float values (1DP)
print_row(N,L) :-
build_row(N,L),
format('~t~1f~10+ ~t~1f~10+ ~t~1f~10+ ~t~1f~10+ ~t~1f~10+ ~n', L).
print_table_header :-
format('~t~w~10+ ~t~w~10+ ~t~w~10+ ~t~w~10+ ~t~w~10+ ~n', ['N','N2','N3','N4','N5']).
would be nice to somehow reuse the code to print the same thing to file.
In addition to the other good answer (+1!), I would like to present a purer solution to such tasks.
The key idea is to make format/2
accessible within DCGs, and then to use a DCG to describe the output.
This is very easy, using the codes
argument of format/3
, provided by several Prolog implementations. All you need are the following short auxiliary definitions:
format_(Data, Args) --> call(format_dlist(Data, Args)).
format_dlist(Data, Args, Cs0, Cs) :- format(codes(Cs0,Cs), Data, Args).
The nonterminal call//1
calls its argument with two additional arguments that let you access the implicit DCG arguments, and this is used to describe additional codes via format/3
.
Now, we can simply use the nonterminal format_//2
within DCGs.
For example, to describe a simple table:
table -->
row([a,b,c]),
row([d,e,f]).
row(Ls) --> format_("~t~w~10+~t~w~10+~t~w~10+~n", Ls).
Usage example and result:
?- phrase(table, Cs), format("~s", [Cs]).
a b c
d e f
Cs = [32, 32, 32, 32, 32, 32, 32, 32, 32|...].
Note that one last remaining format/2
is used to actually write the output to the screen.
However, everything else is free of side-effects and declaratively describes a table.
An important advantage of this method is that you can easily write test cases to see whether your tables are (still) correctly formatted. It is easy to reason about Prolog lists of codes (described with a DCG), but quite hard to reason about things that only appear on the terminal.
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