I want to write a function that can either print something to a string or to an out_channel
. I'm stuck with the internal format
stuff however.
My approach is something like this:
type pr_target = Channel of out_channel | StrRef of string ref
let my_print target fmt = match target with
| Channel ch -> fprintf ch fmt
| StrRef str -> str := !str ^ sprintf fmt
This gives a type errors as the two uses of fmt
are different: fprintf
takes an ('a, out_channel, unit) format
while sprintf
takes an ('a, unit, string) format
.
How can I write such a function? I'm not super proficient with modules or OCamls polymorphism.
Format.formatter can be use either buffers or out_channel as formatting backend:
let b = Buffer.create 10
let bfmt = Format.formatter_of_buffer b
let ch = Out_channel.open_text "filename"
let cfmt = Format.formatter_of_out_channel ch
let either fmt = Format.fprintf (if Random.bool () then bfmt else cfmt) fmt
Moreover, in general, you want to use asprintf
rather than sprintf
in order to be able to use %a
and %t
specifier:
let s =
Format.asprintf "@[<v>This is a list [%a]@]"
Format.(pp_print_list pp_print_string) ["one"; "two"]