2012-04-28 4 views
4

私はF#(特にF#インタラクティブを使って)で研究しているので、 "print-in-in-debug"機能を切り替えたいと思います。F#でprintfnを同等に定義する方法

私は

let dprintfn = printfn 
を行うことができます

F#インタラクティブが

val dprintfn : (Printf.TextWriterFormat<'a> -> 'a) 

を言うと、私は私のスクリプトでいつでも私は

dprintfn "myval1 = %d, other val = %A" a b 

を使用することができます。

それはprintfnで構文と互換性のあることはまだすべての引数を無視するように、今私は、違ったdprintfnを定義したいと思います。どうやって?


私が考えている最も近い(まだ非稼働)変異体である:

let dprintfn (arg: (Printf.TextWriterFormat<'a> -> 'a)) =() 

が、それは次のようにerror FS0003: This value is not a function and cannot be appliedが得られ、その後、dprintfn "%A" "Hello"をコンパイルしません。

P.S.私は現在、回避策としてDebug.WriteLine(...)のエイリアスを使用していますが、F#のタイプシステムを補うための質問はまだ興味深いです。

答えて

10

kprintf関数を使用できます。この関数は、標準の構文を使用して文字列を書式設定しますが、指定した(ラムダ)関数を呼び出して書式設定された文字列を出力します。例えば

、次はdebugが設定され、そうでなければ何もしませんされている場合、文字列を出力します。

let myprintf fmt = Printf.kprintf (fun str -> 
    // Output the formatted string if 'debug', otherwise do nothing 
    if debug then printfn "%s" str) fmt 
+0

、ありがとうございました。しかし、もしあなたが 'printfn'の型を知っていて、同じシグネチャで独自のfuncを定義する方法があれば、それは非常に興味深く役に立ちます。 (あるいは、他の関数と同じように、F#は特定の方法で 'printfn'を扱いますか?) –

+0

文字列のリテラルは、この型に暗黙的に変換できます:http://msdn.microsoft.com/en-us/library/ ee370359.aspxは、魔法の場所です。 – Brian

+1

F#コンパイラは、 'printf'でフォーマットされた文字列と、それらに関連する型の静的解析を特別にサポートしています。 'kprintf'はあなた自身の関数でそれを利用するための標準的な方法です。 – yamen

2

私は自分のアプリケーションをプロファイリングしてきたとデバッグフォーマットが大幅パフォーマンス問題の原因となることがわかりました。デバッグ書式は、アプリケーションの性質上、コードのほとんどすべての文字列で発生します。
明らかに、これは無条件にフォーマットしてからstringを述語に渡すkprintfによって引き起こされています。
最後に、私はあなたのために有用である可能性がある、次の解決策を考え出した:

let myprintf (format: Printf.StringFormat<_>) arg = 
    #if DEBUG 
     sprintf format arg 
    #else 
     String.Empty 
    #endif 

let myprintfn (format: Printf.TextWriterFormat<_>) arg = 
    #if DEBUG 
     printfn format arg 
    #else 
     () 
    #endif 

使い方は非常に簡単で、フォーマットチェックが正常に動作します:これは働いていた

let foo1 = myprintf "foo %d bar" 5 
let foo2 = myprintf "foo %f bar" 5.0 

// can't accept int 
let doesNotCompile1 = myprintf "foo %f bar" 5 
// can't accept two arguments 
let doesNotCompile2 = myprintf "foo %f bar" 5.0 10 

// compiles; result type is int -> string 
let bar = myprintf "foo %f %d bar" 5.0 
関連する問題