There are various convenience functions that you might like to have for printing
out abstract types. In the main part of the lab, we asked you to implement a
`to_string` function so that you could print out values of an abstract type.
Here we describe a slightly different kind of printing function, which you can
integrate directly into the toplevel, making printing your abstract values even
easier. You can also use this printing function to define many other useful
printing functions (such as `to_string`).
### Format functions
If you wish to print values of type `t`, it is useful to provide a function
`format` with the type `Format.formatter -> t -> unit`. This function should
print the value of type `t` onto the given formatter; see "Writing format
functions" below for details.
If you are providing a module type with an abstract type `t`, it's a good habit
to provide a format function for values of type `t`.
### Using format functions
If you have such a function, there are a few useful things you can do with it:
- The `#install_printer` command in the toplevel takes a function of this type
and uses it to print out any results of expressions that have type `t`. For
example:
```
utop# Ints.(one + one);;
- : Ints.t =
utop# #install_printer Ints.format;;
utop# Ints.(one + one);;
- : Ints.t = 2
```
- Recall the `printf` function described in
[the scope, modules, and printing lab](../03-var/rec.html). The
`Format.printf` function has a special flag for printing out user-defined
types using a format function: `"%a"`. Including a `%a` in a format string
will cause `printf` to expect two additional arguments: a formatting function
of type `Format.formatter -> 'a -> t` and a value of type `'a`. For example
```
utop# Format.printf "one in Ints is %a, one in Floats is %a\n"
Ints.format Ints.one
Floats.format Floats.one;;
one in Ints is 1, one in Floats is 1.000
- : unit = ()
```
- The `Format.sprintf` function is like `printf` but returns a string instead
of printing it. It can be used with your formatter to provide a
`to_string` function:
```
utop# let to_string = Format.sprintf "%a" Ints.format;;
to_string : Ints.t -> string =
utop# to_string (Ints.one);;
- : string = "1"
```
- You can use `%a` with `Format.fprintf` (described below) to build formatters
for more complex types out of formatters for simpler types.
### Writing format functions
The easiest way to write a formatting function is using `Format.fprintf`. This
function is like `printf` except that it takes a `Format.formatter` as the first
argument. For example, you might write a character formatting function as
follows:
```
let format_char f = Format.fprintf f "%c"
```
The `Format` module also provides a large number of `pp_print_` functions, but I
find that it's usually easier to simply use `fprintf`.
**Exercise:** Add a `format` function to your `Arith` module type. Implement
it for your `Ints` and `Floats` modules. Use `#install_printer` to add the
printers to the toplevel. Use the `format` functions to write functions
`int_to_string` and `float_to_string` (at the top level, not in the `Ints` or
`Floats` module).
### There's even more
[The Format module](http://caml.inria.fr/pub/docs/manual-ocaml/libref/Format.html)
also has support for automatic line breaking and converting the output into a
variety of formats (such as HTML or even syntax-highlighted output on the
console). For more on automatic line breaking, see
[here](http://caml.inria.fr/resources/doc/guides/format.en.html).
For more information on tags, see
the [`"@{"` and `"@}"` flags to printf](http://caml.inria.fr/pub/docs/manual-ocaml/libref/Format.html#6_printflikefunctionsforprettyprinting),
and the ["semantic tags"](http://caml.inria.fr/pub/docs/manual-ocaml/libref/Format.html#tags) and
["changing the meaning of semantic tags"](http://caml.inria.fr/pub/docs/manual-ocaml/libref/Format.html#tagsmeaning)
sections of the `Format` module documentation.