SSブログ

可変長引数の書式付バイナリ出力関数 [OCaml]

OCaml の printf 関係で検索していたら Caml-list の過去ログ [1] で紹介されていた論文 [2] に ML で printf っぽいものを作る一つのやり方が書いてあった。(ちなみにそのスレッドのフォローアップに OCaml には special
typechecking rules for format strings があるようなことが書いてあるのでやはり printf は特別ということらしい)

さて、[2] を参考に見よう見まねで当初の目的であった書式化バイナリ出力関数を作ってみた。fout というのが作りたかった関数だ。

# let ($) f g x = f (g x);;
val ( $ ) : ('a -> 'b) -> ('c -> 'a) -> 'c -> 'b = <fun>
# let a k s x = k (output_string s x; s);;
val a : (out_channel -> 'a) -> out_channel -> string -> 'a = <fun>
# let c k s x = k (output_char s x; s);;
val c : (out_channel -> 'a) -> out_channel -> char -> 'a = <fun>
# let b k s x = k (output_byte s x; s);;
val b : (out_channel -> 'a) -> out_channel -> int -> 'a = <fun>
# let i k s x = k (output_binary_int s x; s);;
val i : (out_channel -> 'a) -> out_channel -> int -> 'a = <fun>
# let fout out p = p (fun s -> s) out;;
val fout : 'a -> (('b -> 'b) -> 'a -> 'c) -> 'c = <fun>
# let out = open_out_bin "test.dat";;
val out : out_channel = <abstr>
# fout out (c$b$c$b$c$i$a) 'H' 0x65 'l' 0x6c 'o' 542601074 "ld";;
- : out_channel = <abstr>
#
ether@KURO-BOX:~$ od -h -c test.dat
0000000 4865 6c6c 6f20 576f 726c 6400
          H   e   l   l   o       W   o   r   l   d  \0
0000013
ether@KURO-BOX:~$

Obj.magic を使うのとは違って、この仕組みは型チェックがちゃんとなされる安全なものである。

# fout out (c$b$c$b$c$i$a)
  ;;
- : char -> int -> char -> int -> char -> int -> string -> out_channel =
<fun>
# fout out (c$b$c$b$c$i$a) 'H' 0x65 'l' 0x6c 'o' 542601074 'l';;
This expression has type char but is here used with type string

これはかなりいいと思う。少なくとも output_xxx を何行も書くよりはずっといい。
でもちょっと難点もある。それは書式指定を表現するのが文字(列)ではなく関数であるということで、当該名前空間の貴重な1文字識別子を消費してしまう。これは何か嫌だ。あと OCaml 固有の問題として大文字で始まる識別子を関数名に使えないので1文字で表現できる能力が限定される。だからといってあまり書式指定を長い識別子にしたり、モジュールにして例えば Fout.c$Fout.b$... なんて書きたくはない。

[1] http://caml.inria.fr/pub/ml-archives/caml-list/1999/03/f29ccf690732fd68d7c69079a7dc5a92.en.html
[2] http://www.brics.dk/RS/98/12/index.html


nice!(0)  コメント(0)  トラックバック(0) 
共通テーマ:パソコン・インターネット

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。