FIELD NOTES: 書を持って街へ出よう

合同会社フィールドワークス プログラマ兼代表のブログ

pretty printer

今まで,デバッグprintf用にExtLibのStd.printを使ってきたが,フィールド名の情報がなくなってタグ番号の様な数字に化けてしまう。複雑なデータ構造になると直感的に理解できないので,ちょっと不便だなあと思っていたところに,d:id:KeisukeNakano:20081011を見つけた。

「使い方」の部分を見て,見よう見まねでjson-wheelのJson_typeのprety-printerを作ってみた。

(* PP for Json_type *)
let rec pp_json fmt =
  let pp_tuple_string_json =
    pp_tuple (fun (s, j) -> [pp_poly pp_string s;
                             pp_poly pp_json j])
  in
  let pp_dict_item_list = pp_list pp_tuple_string_json in
  let pp_json_list = pp_list pp_json in
  pp_variant (function
                | Json_type.Object o -> "Object", [pp_poly pp_dict_item_list o]
                | Json_type.Array a -> "Array", [pp_poly pp_json_list a]
                | Json_type.String s -> "String", [pp_poly pp_string s]
                | Json_type.Int i -> "Int", [pp_poly pp_int i]
                | Json_type.Float f -> "Float", [pp_poly pp_float f]
                | Json_type.Bool b -> "Bool", [pp_poly pp_bool b]
                | Json_type.Null -> "Null", []) fmt

実行例:

# let j = Json_io.json_of_string("{\"a\": [1,2.0,\"3\"]}");;
val j : Json_type.t = Object [("a", Array [Int 1; Float 2.; String "3"])]
# open ExtLib;;
# Std.print j;;
([("a", Tag1 ([Tag3 (1); Tag4 (2.); Tag2 ("3")]))])
- : unit = ()
# Format.printf "%a@." pp_json j;;
Object([("a", Array([Int(1); Float(2.); String("3")]))])
- : unit = ()

参照型の場合は,こんな感じでいいのかな?

let pp_ref pp_a = pp_record (fun x -> ["contents", pp_poly pp_a x.contents])
let pp_bool_ref = pp_ref pp_bool
let pp_int_ref = pp_ref pp_int
let pp_float_ref = pp_ref pp_float
let pp_char_ref = pp_ref pp_char
let pp_string_ref = pp_ref pp_string

実行例:

# let a = ref 10;;
val a : int ref = {contents = 10}
# Format.printf "%a@." pp_int_ref a;;
{contents = 10}
- : unit = ()