2012-04-28 61 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