Search code examples
ocamlformat-specifiers

Ocaml's sprintf doesn't work with %a format specifier


It seems that sprintf does not allow %a in its format specifier. Is this right? If so, why is it like this, and is there a workaround?

Example. I have a long and complicated datatype:

type t = Foo | Baz

I have a pretty-printer for this type, that sends a string representation of its values to an arbitrary out_channel:

let pp_t oc = function
  | Foo -> fprintf oc "Foo"
  | Baz -> fprintf oc "Baz"

If I then write

let _ = printf "%a=%d" pp_t Foo 2

or

let _ = eprintf "%a=%d" pp_t Foo 2

then everything works fine -- the message "Foo=2" ends up on my stdout or my stderr as expected. But if I write

let s = sprintf "%a=%d" pp_t Foo 2

then I get a compilation error, complaining that the argument pp_t has type out_channel -> t -> unit but an expression was expected of type unit -> 'a -> string.

Is it simply not possible to use %a inside a format specifier for sprintf?


Solution

  • In order to get away with specific datatypes showing up in your formatting functions you should always use the Format module and devise pretty printers for your types that have the signature val pp_t : Format.formatter -> t -> unit; this is also the signature the toplevel asks for to install custom printers with #install_printer for your datatypes.

    Equipped with such a function you can then simply use Format.asprintf with "%a".