我已经编写了许多类型为out_channel -> 'a -> unit
的漂亮打印机,现在我想要一段代码,通过使用漂亮的打印机从值中获取字符串。
例如,我已经实现了以下功能:
type t =
{ x: int;
y: int }
let co = { x = 4; y = 5 }
let print (chan: out_channel) (co: t) : unit =
Printf.fprintf chan "(%d, %d)" co.x co.y
我认为函数Printf.sprintf
可以帮助我获取字符串(4, 5)
。我试过了Printf.sprintf "%a" print co
,它在print
:This expression has type out_channel -> t -> unit but an expression was expected of type unit -> 'a -> string
的位置给了我一个错误。
有没有人知道如何提醒这一行,或者是否有人有sprintf
以外的解决方案?
答案 0 :(得分:3)
出于类型检查的原因,无法在sprintf的格式化指令中直接使用%a
。
如果您能够使用Format
代替Printf
,那么事情就会轻松得多:
Format.asprintf
,根据文档,它会做你想要的。实际上,您必须使用Format.kfprintf
才能使用任意格式化功能:
let sfprintf fmt =
let b = Buffer.create 20 in
let return fmt = Format.pp_print_flush fmt (); Buffer.contents b in
Format.kfprintf return (Format.formatter_of_buffer b) fmt
let s = sfprintf "%a" print co
相同的技术适用于Printf
格式化功能,但此处还有另一个问题:无法从out_channel
创建Buffer.t
。我能想到的最接近的方法是依靠pipe
模块的Unix
函数:
let sfprintf fmt =
let (infd,outfd) = Unix.pipe () in
let inc = Unix.in_channel_of_descr infd in
Unix.set_nonblock infd;
let outc = Unix.out_channel_of_descr outfd in
let return outc =
Printf.fprintf outc "%!";
let b = Buffer.create 10 in
try
while true do
Buffer.add_char b (input_char inc) done;
assert false;
with Sys_blocked_io ->
Unix.close outfd; Unix.close infd; Buffer.contents b
in
Printf.kfprintf return outc fmt;;
let s = sfprintf "%a" print co
答案 1 :(得分:0)
我担心我不清楚你需要什么,所以让我猜一下:
let prints (co: t) : string =
Printf.sprintf "(%d, %d)" co.x co.y
let print ch co = Printf.fprintf ch "%s" (prints co)
# print stdout co;;
(4, 5)- : unit = ()