由于我使用F#进行研究(特别是使用F#interactive),我希望能够切换“print-when-in-debug”功能。
我能做到
let dprintfn = printfn
F#interactive说
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#的类型系统仍然很有用。
答案 0 :(得分:11)
您可以使用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
答案 1 :(得分: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
用法非常简单,格式检查工作正常:
{{1}}