/// Colored printf
let cprintf c fmt =
Printf.kprintf
(fun s ->
let old = System.Console.ForegroundColor
try
System.Console.ForegroundColor <- c;
System.Console.Write s
finally
System.Console.ForegroundColor <- old)
fmt
// Colored printfn
let cprintfn c fmt =
cprintf c fmt
printfn ""
cprintfn ConsoleColor.Yellow "This works"
但是
cprintfn ConsoleColor.Yellow "This %s" "doesn't"
(cprintfn ConsoleColor.Yellow) "still %s" "doesn't"
(cprintfn ConsoleColor.Yellow "still %s") "doesn't"
cprintfn ConsoleColor.Yellow ("still %s" "doesn't")
我知道这与Printf.TextWriterFormat<_>
vs简单字符串有关,但即使在fmt
中指定cprintf c (fmt:Printf.TextWriterFormat<_>)
的类型,我也无法让kprintf部分工作。我阅读了一些与日志记录相关的答案,但我仍然无法弄明白。 cprintf是否可以采用格式参数?
答案 0 :(得分:6)
首先,您的cprintf
函数非常好,您可以使用可变数量的参数。问题仅出在cprintfn
函数:
cprintf System.ConsoleColor.Red "%s %d" "hi" 42
问题在于,当您定义使用格式化字符串的函数时,您始终需要使用部分应用程序。那就是你的功能必须是以下形式:
let myprintf fmt =
<whatever>
otherprintf <whatever> fmt
重要的是otherprintf <whatever> fmt
必须是身体的最后一部分,并且必须以fmt
作为最后一个参数。这样,当otherprintf
需要更多参数(由fmt
指定)时,这些参数会自动传播并成为myprintf
的参数。
这意味着根据cprintfn
定义cprintf
实际上非常棘手。但是你总是可以定义一个功能更强大的辅助函数,让你同时做到这两点:
let cprintfWith endl c fmt =
Printf.kprintf
(fun s ->
let old = System.Console.ForegroundColor
try
System.Console.ForegroundColor <- c;
System.Console.Write (s + endl)
finally
System.Console.ForegroundColor <- old)
fmt
let cprintf c fmt = cprintfWith "" c fmt
let cprintfn c fmt = cprintfWith "\n" c fmt