我要調試打印添加到我的項目與具有類型簽名類似的功能:如何管理在F#調試印刷
bool -> Printf.TextWriterFormat<'a> -> 'a
也就是說,它應該採取一個布爾值,表明我們是否是在詳細模式,並用它來決定是否打印。
例如,讓我們說dprint : bool -> Printf.TextWriterFormat<'a> -> 'a
然後我想這種行爲:
> dprint true "Hello I'm %d" 52;;
Hello I'm 52
val it : unit =()
> dprint false "Hello I'm %d" 52;;
val it : unit =()
的想法是,一個命令行標誌可用於避免控制此輸出。我還想避免在「非冗長」情況下的運行時成本。這是可能使用kprintf
定義是這樣工作的一個函數:
let dprint (v: bool) (fmt: Printf.StringFormat<'a,unit>) =
let printVerbose (s: string) =
if v then System.Console.WriteLine(s)
fmt |> Printf.kprintf printVerbose
但印刷/忽略數字序列與List.iter (dprint b "%A") [1..10000]
(b中\ {TRUE,FALSE})開量爲1.5秒B的兩個值在我的機器上。
我想出了另一種方法,使用的反映,建立適當類型的函數放棄格式化參數:
let dprint (v: bool) (fmt: Printf.TextWriterFormat<'a>) : 'a =
let rec mkKn (ty: System.Type) =
if FSharpType.IsFunction(ty) then
let _, ran = FSharpType.GetFunctionElements(ty)
FSharpValue.MakeFunction(ty,(fun _ -> mkKn ran))
else
box()
if v then
printfn fmt
else
unbox<'a> (mkKn typeof<'a>)
但這裏的反射似乎過於昂貴(甚至比裏面的標準庫複雜完成有時定義爲printf
)。
我不想我的垃圾帶之類的東西代碼:
if !Options.verbose then
printfn "Debug important value: %A" bigObject5
或關閉:
dprint (fun() -> printfn "Debug important value: %A" bigObject5)
所以,有沒有其他解決辦法?
這是一個非常有趣的建議,謝謝。它似乎並不像預期的那樣緩存 - 它在我的問題中的List.iter示例中很慢。我嘗試添加一個字典到'Format'來顯式緩存這些函數,但是這似乎也不起作用。也許'unbox'或'typeof'是昂貴的。 – rneatherway 2012-07-19 13:47:12
@robin,我現在看到'mkKn'的問題,讓我編輯.. – t0yv0 2012-07-19 14:03:14
@robin - 我認爲與上述修正應該只用於第一次調用(每種類型)。然而,仍然存在調用形式爲'(fun x y z - >())x y z'的未優化curry關閉的代價,包括'MakeFunction'引入的裝箱效果。 – t0yv0 2012-07-19 14:06:27