Format unnusual features
The OCaml Format module contains many features that are easy to miss at first
glance. This blog post proposes a small tour of some of the less known
features of Format.fprintf
.
Conversion specifications within boxes
First, let’s have a look at a Format
combinator that takes a printer
and encapsulate inside a box:
If we have a custom printer, for instance, for a list of int
Then the box
and vbox
combinators make it easy to choose the interpretation
of the break hints inside the list
[1, 2, 3]
One issue with those functions is that we need one function for each box kind and for each choice of indentation. Is it possible to generalize this function and pass the kind and the indentation of the box as an argument? Surprisingly, a possible solution is to add conversion specifications inside the box definition:
Going further, it is possible to avoid the string-typed box by defining
Then, we can switch to a vertical display for our int list with
1, 2, 3
This trick also works with tags rather than boxes
Subformat substitution
Another rarely used feature of Format.fprintf
is subformat substitution.
Consider for instance an integer vector type:
A printer for this type may be written as
However, a problem with this printer is that the integer format is fixed.
It is no longer possible to choose a padding size with "%3d"
, or an
hexadecimal base with "%x"
. Subformat substitution can resolve this issue.
Here, the conversion specification %(%d)
takes as an argument
a format string which itself takes an integer as argument,
and then substitutes this format string inside the parent format string.
Another curiosity is to use a substitution conversion specification without a specifier
Here, %(%)
accepts as an argument any format string without any conversion
specification. In other words, %(%)
is a version of %s
that allows
formatting hints.
It is also possible to use this format substitution in a more complex settings,
but this does not feel very practical.
Padding and precision
Another interesting way to customize the printing of basic type are the padding and precision argument modals. Numeric specifiers can be adjoined a padding size:
00005
This padding size determines the minimum size of the output. Moreover, here, the leading 0 indicates that the output should be padded by 0. Similarly, for floats, the precision modal determines the number of fractional digits
0.52
Those explicit padding and precision modals can also be provided as an
argument of fprintf
by replacing the numerical value by *
Format type specifier printer
An even more anecdotal features of Format.fprintf
is the printing of
the canonical type specification of a format string, also known as %{...%}
%a
The specifier %{fmt%}
prints the type specification
of the format given as an argument and of which the type is compatible
with the format argument fmt
. In other words, in many cases,
%{fmt%}
is a very involved way to print fmt
.
However, the two strings can differ slightly when non-canonical
conversion specification are used:
%i%i%f
Note that %{...%}
is more useful on the Scanf
side.