0

sprintfまたはのように動作するトレース関数を作成するように設定しましたprintfnが、ConditionalAttribute.

これまでの結果: ありえないと思います。

Conditional("DEBUG")問題は、属性を使用する場合、関数が単位の結果を返さなければならないという事実に集中しています。「通常の」引数は正常に機能し、メソッドは適切に装飾されています (編集:装飾されていますが、カリー化可能なメンバーは消去されていません。議論を参照してください。代わりにタプル形式を使用する必要があります):

type Trace() =    
    [<Conditional("DEBUG")>]
    static member inline trace msg b = (msg, b) |> ignore

// using it, x is unit
let x = Trace.trace "test" "foo"

ignore(がないと、Conditional 属性のためにコンパイルされないことに注意してください)

しかし、 のバリアントを試すとすぐPrintf.TextWriterFormat<'T>に失敗し、それを回避する方法がわかりません。

type Trace() =
    [<Conditional("DEBUG")>]
    static member inline trace msg = printfn msg    // inline or not doesn't matter

    // using it, x is unit
    let x = Trace.trace "hello: %s" "foobar"

これは属性なしで機能しますが属性を使用すると、次のようになります。

この式には型があると予想されて
      unit
いましたが、ここには型があります
      string -> unit

エラーには具体的に下線が引かれてTrace.trace "hello: %s"います。したがって、コンパイラは、式全体が になることを認識していないように見え、unitを返すラッパー関数を内部的に作成するため、エラーが発生しますstring -> unit。これは、 の規則では許可されていませんConditionalAttribute

:unit関数の戻り値の型を明示的に指定するかprintfn msg |> ignore、本体として修正しようとすると、テキスト ライターの書式指定文字列をタイプ セーフで使用できなくなります。実際には、呼び出しの 2 番目の引数が認識されません。 -サイトはもうありません。

したがって、関数シグネチャ全体は CLR の規則に従いますが、F# が作成するインライン関数は、少なくともこの特定のケースではそうではないようです。

を含むバリアントを試してkprintfsprintfそれが役立つかどうかを確認しましたが、すべて役に立ちませんでした。

何か案は?それとも、これは、カーペットを敷こうとして、一方の角を適切に滑らかにすると、もう一方の角で泡立ち、逆の場合、つまり収まらないという状況の 1 つですか?


PS:なぜ私がそれを望んでいるのか疑問に思っている場合: 既存の Trace のように動作する便利な関数を作成しようとしていますが、内部では他の機能が実行されています。私が現在持っているものは機能しますが、静的に型チェックされた引数ではなく文字列を取るだけなので、ユーザーは次のようなものを書く必要があります:

(sprintf "Hello %s" >> Trace.trace) "foobar"
4

1 に答える 1

3

オーバーロード ベースのバージョン。

さらにオーバーロードが必要になる場合があります

#if DEBUG
type Log() =
    static member inline log(x) = printfn x
    static member inline log(x,y) = printfn x y
#else
type Log =
    static member inline log(x) = ()
    static member inline log(x,y) = ()
#end

アップデート:

したがって、これは機能します:

open System.Diagnostics
type Log() =
    [<Conditional("DEBUG")>]  
    static member log(x) = printfn x
    [<Conditional("DEBUG")>]
    static member log(x,y) = printfn x y

カリー化されたものはオーバーロードできないため、オーバーロードを可能にするためにタプル形式に切り替え、タプル形式を使用する必要があります

于 2015-11-19T10:48:25.100 に答える