使用序言格式谓词打印到文件

Using the prolog format predicate to print to file

是否可以使用 prolog format 谓词打印到文件?

我有一个 table 数据,我使用格式谓词打印到标准输出,即

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']).

最好能以某种方式重用代码以将相同的内容打印到文件中。

你可以!

考虑 SICStus Prolog documentation for format/[2,3] 的以下摘录:

11.3.85 format/[2,3]

Synopsis

format(+Control, +Arguments)

format(+Stream, +Control, +Arguments)

Interprets the Arguments according to the Control string and prints the result on Stream.

谓词 format/[2,3] 在 Prolog 实现中得到广泛支持。

但是,截至目前,这些谓词还不是 ISO Prolog 的一部分。

我会用一个附加参数 Stream 编写输出 'routines',然后我会在测试或打印到屏幕时传递 user。请参阅 ISO 谓词 open/3、close/1 等以进行流处理...

请注意,IO 它是语言中最少 'declarative' 的领域之一,因为为了提高效率,需要一种基于副作用的方法...

SWI-Prolog 有一个内置的with_output_to, that would allows to reuse your existing code without adding a parameter. But since you tagged 你的问题,你真的应该添加 Stream 参数...

除了另一个好的答案(+1!)之外,我想为此类任务提供一个更纯粹的解决方案。

关键思想是让 format/2 在 DCG 中可访问,然后使用 DCG 来描述输出。

这非常简单,使用 format/3codes 参数,由多个 Prolog 实现提供。您只需要以下简短的辅助定义:

format_(Data, Args) --> call(format_dlist(Data, Args)).

format_dlist(Data, Args, Cs0, Cs) :- format(codes(Cs0,Cs), Data, Args).

非终结符 call//1 使用两个附加参数调用其参数,使您可以访问隐式 DCG 参数,这用于通过 format/3.

描述附加代码

现在,我们可以简单地在 DCG 中使用非终结符 format_//2

例如描述一个简单的table:

table -->
    row([a,b,c]),
    row([d,e,f]).

row(Ls) --> format_("~t~w~10+~t~w~10+~t~w~10+~n", Ls). 

使用示例和结果:

?- phrase(table, Cs), format("~s", [Cs]).
         a         b         c
         d         e         f
Cs = [32, 32, 32, 32, 32, 32, 32, 32, 32|...].

请注意,最后剩下的 format/2 用于实际将输出写入屏幕。

但是,其他一切都没有副作用,并且声明性地描述了一个 table。

此方法的一个重要优点是您可以轻松编写 测试用例 以查看您的 table 是否(仍然)正确格式化。推导 Prolog 代码列表(用 DCG 描述)很容易,但推导只出现在终端上的东西却很困难。