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# が作成するインライン関数は、少なくともこの特定のケースではそうではないようです。
を含むバリアントを試してkprintf
、sprintf
それが役立つかどうかを確認しましたが、すべて役に立ちませんでした。
何か案は?それとも、これは、カーペットを敷こうとして、一方の角を適切に滑らかにすると、もう一方の角で泡立ち、逆の場合、つまり収まらないという状況の 1 つですか?
PS:なぜ私がそれを望んでいるのか疑問に思っている場合: 既存の Trace のように動作する便利な関数を作成しようとしていますが、内部では他の機能が実行されています。私が現在持っているものは機能しますが、静的に型チェックされた引数ではなく文字列を取るだけなので、ユーザーは次のようなものを書く必要があります:
(sprintf "Hello %s" >> Trace.trace) "foobar"