Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using the prolog format predicate to print to file

Tags:

prolog

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.

like image 872
bph Avatar asked Jan 08 '23 21:01

bph


1 Answers

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.

like image 61
mat Avatar answered Jan 15 '23 01:01

mat