#install_printer
多分、普通のプリンタの作り方だとこんな感じです。
let print_sring ppf str = Format.fprintf ppf "utf8_of_string \"%s\"" str;; #install_printer print_string;;
型が、Format.formatter -> 'a -> unitになるような関数を作って、#install_printerしてあげると、'a型の値のプリンタになる。のだと思っていたら、'a -> unitでもOKだったのですね…しかも上手く動かないと。LXはアホか。
PrintfモジュールがFormatモジュールのラッパーになっているようなイメージです。Formatモジュールのfprintとかpp_print_stringとかは、Format.formatter型の引数を受け付けるようになっているのですが(ppf = pretty printing formatterという仮引数がそれです)、その引数に破壊的に操作するようになっているみたいです。
Printfモジュールは、Formatモジュールの関数にデフォルトのformatterを部分適用したような感じで定義されているイメージです。ですのでFormatモジュールの関数と混ぜると、どのppfをどの順序で操作しているのかよくわからなくなって、出力順がおかしくなることがあるのだと理解しています。
ちなみにFormatモジュールの真価は、%aと@,だと思ってます。%aで自分の作ったプリンタ(=Format.formatter -> 'a -> unit型の関数)を繋げていって、@,で整形、というのは、割と便利だと思います。%aが型付きなのもポイントです。
上のと同じ動作をするプリンタを無理やり%aを使って書くと、こんな感じになります。
let print_sring ppf str = Format.fprintf ppf "utf8_of_string \"%a\"" Format.pp_print_string str;; #install_printer print_string;;
let f a = ();; #install_printer f;;
とかすると、ちょっと愉快ですね。