如何编写带有可变数量参数的F#printfn的自定义版本?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何编写带有可变数量参数的F#printfn的自定义版本?相关的知识,希望对你有一定的参考价值。
我想写一个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函数的正确方法是什么。
答案
这可以用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
另一答案
我想通过移动函数的时间读出来证明这一点,原因有两个。主要是为了演示如何添加一个或多个不被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中格式化它似乎不是一个好主意。
ksprintf未使用的参数在tsprintf中显式声明。 ksprintf的格式字符串和以下参数未明确声明,但它们遵循所有显式声明的参数。
以上是关于如何编写带有可变数量参数的F#printfn的自定义版本?的主要内容,如果未能解决你的问题,请参考以下文章