I defined a custom pretty-printer that takes a message, customise it and prints it:
let mypp ppf msg =
Format.fprintf ppf "Hello";
Format.fprintf ppf msg
Now, I wanted to use it to print to a string but since I want to use it multiple times I wanted to put it in a function:
let myspp msg =
let _ = mypp Format.str_formatter msg in
Format.flush_str_formatter ()
But I can't write what I want:
12 | let s = myspp "Bleh %s" "world" in
^^^^^
Error: This function has type ('a, Format.formatter, unit) format -> string
It is applied to too many arguments; maybe you forgot a `;'.
Even worse, if I delete the argument:
let () =
let s = myspp "Bleh %s" in
Format.eprintf "---%s---@." s
Results in:
---Hello: ---
The formatting string disappeared.
I know I'm missing something but can't find it. I tried using kfprintf
but didn't have good results. Maybe I need to change my original function?
It should be noted that if I don't use it in a function it works as wanted:
let () =
mypp Format.str_formatter "Blah %s" "blih";
Format.eprintf "---%s---@." (Format.flush_str_formatter ())
Results in:
---Hello: Blah blih---
Since you want to run some function after that all format arguments have been provided, the only option is to use kfprintf
:
let to_string msg =
let b = Buffer.create 17 in
let ppf = Format.formatter_of_buffer b in
Format.fprintf ppf "Hello: ";
Format.kfprintf (fun ppf ->
Format.pp_print_flush ppf ();
Buffer.contents b
) ppf msg
let s = to_string "%d + %d = %d" 1 2 3
It is also better to avoid Format.str_formatter
since this avoid introducing a global mutable state in your program.
EDIT:
If the important point is to reuse the mypp
function, the simplest fix is to add a continuation argument to mypp
:
let kmypp k ppf msg =
Format.fprintf ppf "Hello";
Format.kfprintf k ppf msg
let to_string msg =
let b = Buffer.create 17 in
let ppf = Format.formatter_of_buffer b in
kmypp (fun ppf ->
Format.pp_print_flush ppf ();
Buffer.contents b
) ppf msg