2011-07-06 11 views
7

printffprintfなど:すべてが%aの変換を受け入れます。OCamlのユーザ定義プリンタ

マニュアルは%aため言う:。

「ユーザ定義プリンタ二つの引数を取り、(現在の出力チャネル)outchanする最初のものを適用し、第二の引数することは、最初の引数を持たなければなりません。 out_channel - > 'b - >単位と2番目の' b。関数によって生成された出力は、現在の点でfprintfの出力に挿入されます。

私はユーザー定義のプリンタが何であるか、そしてそれをどのように実装して使用するのか理解できません。誰かが動機づけを説明し、例を提供することはできますか?

たとえば、複雑なデータ構造体を印刷する場合、カスタム関数を使用してデータ構造体を直接文字列に出力したり出力したりすることができないのはなぜですか?

+0

'sprintf'と' 'ユニットの機能を取るksprintf' - >「 - >文字列 'のようなものです。 – nlucaroni

+0

私の質問はおそらく非常に不正確でした。私が知りたいことは、文字列( 'printf'や'%s'や 'sprintf'や' ksprintf'など)に印刷するのではなく、 '%その文字列を使って他のことを行います。たとえば、チャンネルに出力するなどです。 – ndbd

答えて

2

あなたは、「自分のデータ構造を印刷する」ことができます。代わりに"%a"を使用するのが文体的な選択かもしれません。それはいくつかの点で一貫しているように見えます。

32ビットシステムでは、文字列の長さは約16MBに制限されています。したがって、"%a"が動作し、"%s"が失敗するケースを想像することができます。中間文字列がこれより長い場合。私はこれを実践したことはありませんでした。私はちょうど"%s"を使っています。

5

「複雑なデータ構造だけを印刷する」とはどういう意味ですか?データ構造体を文字列に変換する関数を定義すると、これを行うことができます。データ構造体を「デフォルト表現」(「http://caml.inria.fr/cgi-bin/hump.en.cgi?sort=0&browse=139」を参照)で「ダンプ」することも可能ですが、それは他のものよりもデバッグのためのものです。

と言われています。 %aのための非常に単純な例では:あなたが機能TYが-> string、あなたのデータを印刷する"%s"でそれを使用することができます持っているので、私は現実的な例で考えた場合

type ty = A | B 

let ty_to_string = function 
    | A -> "A" 
    | B -> "B" 

let print_ty chan v = output_string chan (ty_to_string v) 

let _ = Printf.printf "%a" print_ty A 
+0

私が理解しづらいのは、 が_ = Printf.printf "%s"(ty_to_string A)または が_ = Printf.fprintf stdout "%s"(ty_to_string A)としていることです。少なくとも後者は、上記の例で%aを使用するのと同様に、どのチャネルに出力するかについて何らかの抽象化を提供していますか? – ndbd

+2

物事は、大きな構造体のために文字列への変換はコストがかかる(考えてみてください:文字列の連結)。可能であれば、チャンネルに直接書き込む方がはるかに効率的です。そして、あなたが '%a'のような関数を持っていれば、自然に入ります。 – akoprowski

1

%aを使用すると、 "%s"ではなく出力チャネルに直接印刷し、印刷したい値を文字列にしてから印刷することができます。

この区別は、シリアル化されたデータを出力チャネルに直接送信することが可能で合理的である場合には、潜在的に大きな文字列を割り当てる(または指数関数のサイズ変更とコピーを使用してバッファを使用する) ? Jeffreyは、文字列の長さのせいで、非常に大きなシリアル化が32ビットシステムで失敗する可能性があることを非常に正しく指摘しています。

私はバッテリー使用して、私のコードでは、多くの場合、%aを使用する私の値のカスタムプリンタを構築するために構成可能な印刷機能を:

let range_print oc r = 
    let print_one oc (a,b) = fprintf oc "%d:%d" a b in 
    List.print ~first:"" ~last:"" ~sep:"," print_one oc r 
let print_rule print_pred print_dec oc r = 
    fprintf oc "%a,%a" print_pred r.pred print_dec r.dec 
let print_item oc x = print_rule range_print Int.print oc x in 
... 
printf "IN : %a\nOUT: %a\n" print_item a print_item b; 
関連する問題