7

私は F# で (特に F# インタラクティブを使用して) 研究を行っているので、切り替え可能な「デバッグ時に出力」機能が必要です。

できます

let dprintfn = printfn

F#インタラクティブ 言う

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

そして私は使用することができます

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

スクリプトでいつでも。

dprintfnここで、別の方法で定義したいと思います。これにより、すべての引数が無視されますが、printfn. どのように?


私が考えている最も近い(まだ機能していない)バリアントは次のとおりです。

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

しかし、次はコンパイルされずdprintfn "%A" "Hello"、結果はerror FS0003: This value is not a function and cannot be applied.

PSDebug.WriteLine(...)現在、回避策としてエイリアスを使用していますが、F# の型システムを理解する上で興味深い質問です。

4

2 に答える 2

11

標準構文を使用して文字列をフォーマットする関数を使用できますが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
于 2012-04-28T17:26:55.507 に答える
3

アプリケーションのプロファイリングを行ったところ、デバッグ フォーマットが重大なパフォーマンスの問題を引き起こしていることがわかりました。アプリケーションの性質上、コードのほぼすべての文字列でデバッグの書式設定が行われます。
明らかに、これはkprintfwhich が無条件にフォーマットしてstringから a を述語に渡すことが原因です。
最後に、私はあなたに役立つかもしれない次の解決策を思いつきました:

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
于 2012-07-05T21:49:47.707 に答える