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 = <abstr> 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 = <fun> 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.