Since I do research with F# (in particular, using F# interactive), I'd like to have switchable "print-when-in-debug" function.
I can do
let dprintfn = printfn
F# interactive says
val dprintfn : (Printf.TextWriterFormat<'a> -> 'a)
and I can use
dprintfn "myval1 = %d, other val = %A" a b
whenever I want in my scripts.
Now I'd like to define dprintfn
differently, so that it would ignore all its arguments yet being syntax-compatible with printfn
. How?
The closest (yet non-working) variant I have in mind is:
let dprintfn (arg: (Printf.TextWriterFormat<'a> -> 'a)) = ()
but it the following doesn't compile then dprintfn "%A" "Hello"
, resulting in error FS0003: This value is not a function and cannot be applied
.
PS I currently use an alias for Debug.WriteLine(...)
as work-around, but the question is still interesting for understading F#'s type system.
You can use the kprintf
function, which formats a string using the standard syntax, but then calls a (lambda) function you specify to print the formatted string.
For example, the following prints the string if debug
is set and otherwise does nothing:
let myprintf fmt = Printf.kprintf (fun str ->
// Output the formatted string if 'debug', otherwise do nothing
if debug then printfn "%s" str) fmt
I've been profiling my application and found that debug formatting causes significant performance issues . Debug formatting occurs on almost every string of the code, due to the nature of the application.
Obviously, this has been caused by kprintf
which unconditionally formats and then passes a string
to a predicate.
Finally, I came up with the following solution that may be useful for you:
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
Usage is quite simple, and format checking works fine:
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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.