4.32 Formatted Write

The format family of predicates is the most versatile and portable way to produce textual output. These predicates where introduced by Quintus Prolog. The SWI-Prolog implementation is compatible with PIP-0110. SWI-Prolog implements a couple of extensions:

format(+Format)
format(+Format, :Arguments)
format(+Output, +Format, :Arguments)
Write formatted output to Output or current_output. Format is an atom, list of character codes, or a Prolog string. Arguments is a list of arguments required by the format specification. For backward compatibility, if Format needs exactly one argument and the required argument is not a list, single argument needs not be nested in a list. This feature is deprecated as it easily leads to mistakes and make static analysis by check/0 less accurate.

Output is normally a stream. SWI-Prolog's format/3 also accepts any other output accepted by with_output_to/2. For example:

?- format(atom(A), '~D', [1000000]).
A = '1,000,000'

Format control sequences start with the tilde (~), followed by an optional numeric argument, optionally followed by a colon modifier (:), 144The colon modifiers is a SWI-Prolog extension, proposed by Richard O'Keefe. followed by a character describing the action to be undertaken. A numeric argument is either a sequence of digits, representing a positive decimal number, a sequence ‘<character>, representing the character code value of the character (only useful for ~t) or an asterisk (*), in which case the numeric argument is taken from the next argument of the argument list, which should be a positive integer or an arithmetic expression that evaluates to a possitive integer. The following four examples all pass 46 (.) to ~t and use a tab at 72.

?- format('~w ~46t ~w~72|~n', ['Title', 'Page']).
?- format('~w ~`.t ~w~72|~n', ['Title', 'Page']).
?- format('~w ~*t ~w~72|~n', ['Title', 46, 'Page']).
?- format('~w ~*t ~w~*|~n', ['Title', 46, 'Page', 80-8]).

Some format expressions may call back Prolog, i.e., ~p, ~W, ~@ and user defined extensions registered with format_predicate/2. Output written to the stream current_output is merged into the format/2 output. If there is no pending rubber (~t) and the the position notation aligns, only the output is switched. Otherwise the output is captured in a temporary memory buffer and emitted after the callback finishes. The system attempts to preserve the position and alignment promises. It sets the tty property of the temporary stream to reflect the main stream and uses the position information of the temporary stream to update its notion of the position. Notable ansi_format/3 cooperates properly in callbacks.145As of version 8.3.30.

Numeric conversion (d, D, e, E, f, F, g, G, h and H) accept an arithmetic expression as argument. This is introduced to handle rational numbers transparently (see section 4.27.2.2). The floating point conversions allow for unlimited precision for printing rational numbers in decimal form. E.g., the following will write as many 3's as you want by changing the‘50’.

?- format('~50f', [10r3]).
3.33333333333333333333333333333333333333333333333333

Example:

simple_statistics :-
    <obtain statistics>         % left to the user
    format('~tStatistics~t~72|~n~n'),
    format('Runtime: ~`.t ~2f~34|  Inferences: ~`.t ~D~72|~n',
                                            [RunT, Inf]),
    ....

will output

                             Statistics

Runtime: .................. 3.45  Inferences: .......... 60,345

4.32.1 Programming Format

format_predicate(+Char, +Head)
If a sequence ~c (tilde, followed by some character) is found, the format/3 and friends first check whether the user has defined a predicate to handle the format. If not, the built-in formatting rules described above are used. Char is either a character code or a one-character atom, specifying the letter to be (re)defined. Head is a term, whose name and arity are used to determine the predicate to call for the redefined formatting character. The first argument to the predicate is the numeric argument of the format command, or the atom default if no argument is specified. The remaining arguments are filled from the argument list. The example below defines ~T to print a timestamp in ISO8601 format (see format_time/3). The subsequent block illustrates a possible call.
:- format_predicate('T', format_time(_Arg,_Time)).

format_time(_Arg, Stamp) :-
        must_be(number, Stamp),
        format_time(current_output, '%FT%T%z', Stamp).
?- get_time(Now),
   format('Now, it is ~T~n', [Now]).
Now, it is 2012-06-04T19:02:01+0200
Now = 1338829321.6620328.
current_format_predicate(?Code, ?:Head)
True when ~Code is handled by the user-defined predicate specified by Head.