2017-05-26 37 views
3

我試圖創建2個日誌記錄功能:一個是直接打印到標準輸出,另一個是與先行詞串[Error]打印。連續登錄F#

let log message = 
    printfn message 

let twError (tw:System.IO.TextWriter) message = 
    tw.Write("[Error] {0}", message) 

let error (message:Printf.StringFormat<_>) = 
    let format = Printf.TextWriterFormat<_>(sprintf "[Error] %A" message) 
    log format 

let date = System.DateTime.Now 
log "%A" twError date 
error "%s" <| date.ToString() 

正如你所看到的,在error功能我需要一個新的字符串,然後將其轉換爲TextWriterFormat類型。但是,這會比直接寫入流的效率低,我應該如何更改error函數以使其更高效?

回答

3

您希望Printf.kprintf家庭的功能。他們的文檔非常很難理解,但這個概念很簡單:

  • printf需要一個格式字符串(和參數),格式,然後它打印到控制檯
  • sprintf需要一個格式字符串(和參數),將其格式化,然後返回作爲一個字符串
  • kprintf需要一個格式字符串(和參數),格式,然後將其傳遞(作爲一個字符串),以您提供的功能。該函數應該接受一個字符串並根據需要做任何事情。

例如:

open Printf 

let addDateTime (s : string) = 
    sprintf "%A: %s" DateTime.UtcNow s 

sprintf "%A" [1; 2; 3] // Returns "[1; 2; 3]" 
kprintf addDateTime "%A" [1; 2; 3] // Returns "2017-05-26 06:05:00: [1; 2; 3]" 

let printDateTime (s : string) = 
    printfn "%A: %s" DateTime.UtcNow s 

printfn "%A" [1; 2; 3] // Prints "[1; 2; 3]" 
kprintf printDateTime "%A" [1; 2; 3] // Prints "2017-05-26 06:05:00: [1; 2; 3]" 

所以你error功能可以簡單地變成:

let errorLogger (s : string) = printfn "[Error] %s" s 
let error msg = kprintf errorLogger msg 

error "Oops: %A" [1; 2; 3] // Prints "[Error] Oops: [1; 2; 3]" 

實驗與kprintf多一點,看看你可以用它做什麼。這是一個非常強大的功能,讓更多人不知道它是一種恥辱。

+1

答案是好的,但我也發現,有很多重複或接近重複的,這提供了額外的信息和示例。搜索'[f#] kprintf'。 –

+0

@BentTranberg當我和您的查詢搜索,我發現'kprintf'慢得多比較'TextWriter',有沒有一樣快'TextWriter'其他方法? – MiP

+0

@MiP - 你在哪裏發現'kprintf'比'TextWriter'慢?我一直無法找到您正在查看的來源。另外,你爲什麼需要它快速?這聽起來像你可能會做過早的優化。 – rmunn