我想编写F#printfn函数的扩展版本,该功能除了显示文本外还显示当前时间。像这样:
let printimefn fmt =
let time = DateTime.Now
let strtime = sprintf "%02d:%02d:%02d" time.Hour time.Minute time.Second
printfn "%s %A" strtime fmt
不幸的是,这无法按预期进行。 “ fmt”参数丢失其类型Printf.TextWriterFormat <'T>。
我可以通过使用类型注释来强制其类型:
let printimefn (fmt : Printf.TextWriterFormat<'T>) =
let time = DateTime.Now
let strtime = sprintf "%02d:%02d:%02d" time.Hour time.Minute time.Second
printfn "%s %A" strtime fmt
但是,printimefn的结果变成单位,而不是'T。因此它仍然不起作用。我想知道编写自定义printfn函数的正确方法是什么。
答案 0 :(得分:4)
这可以通过Printf.ksprintf
let printimefn fmt =
let time = DateTime.Now
Printf.ksprintf (
fun s ->
printfn "%02d:%02d:%02d %s" time.Hour time.Minute time.Second s)
fmt
答案 1 :(得分:0)
出于两个原因,我想通过将时间的读数移出函数来演示这一点。主要是为了演示如何添加一个或多个ksprintf不使用的参数,还因为我们应该具有一个没有副作用的函数。如果要在函数中读取时间,则可以创建一个包装器来读取时间,然后调用以下函数。
首先,有两个未传递给ksprintf的显式参数。然后隐式跟随格式字符串和格式字符串所需的任何隐式参数。
let tsprintf (dateTime: DateTime) (tag: string) =
let dateTimeString =
dateTime.ToString (@"yyyy/MM/dd HH:mm:ss",
System.Globalization.CultureInfo.InvariantCulture)
Printf.ksprintf (fun formatString ->
"[" + dateTimeString + " <" + tag + ">] " + formatString)
let testTime = DateTime(1987, 12, 31, 11, 59, 58)
let message = tsprintf testTime "007" "Hello %s!" "James Bond"
message.Dump() // LINQPad output : [1987/12/31 11:59:58 <007>] Hello James Bond!
将InvariantCulture与选定的时间格式字符串结合使用,可以确保无论在何处或什么地方,您看到的结果都是末尾注释中的内容。
我使用DateTime.ToString的原因是,无论您使用哪种方式,它都会格式化DateTime。在ksprintf中格式化它似乎不是一个好主意。
在tsprintf中显式声明了ksprintf不使用的参数。 ksprintf的格式字符串和以下参数未显式声明,但它们遵循所有显式声明的参数。