2012-04-28 60 views
4

printfn相當於,因爲我研究與F#(尤其是使用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

P.S.我目前使用Debug.WriteLine(...)的別名作爲解決方法,但這個問題對於F#的類型系統的替換仍然很有趣。

回答

10

可以使用kprintf功能,其格式使用標準語法的字符串,但隨後調用(lambda)函數指定要打印的格式化字符串。

例如,下面的打印,如果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',不只是像任何其他功能?) – 2012-04-28 17:47:55

+0

字符串常量是隱式轉換爲這種類型:http://msdn.microsoft.com/en-us/library/ ee370359.aspx這是魔術的地方。 – Brian 2012-04-28 20:01:25

+1

F#編譯器特別支持'printf'格式化的字符串以及與它們關聯的類型的靜態分析。 'kprintf'是在你自己的功能中利用它的標準方式。 – yamen 2012-04-28 21:30:05

2

我一直在剖析我的應用程序,發現調試格式導致顯著性能問題。由於應用程序的性質,調試格式幾乎發生在每個代碼字符串上。
顯然,這已經通過kprintf其無條件格式化,然後通過一個string到謂詞引起的。
最後,我想出了以下的解決方案,可能對您有用:

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