我将 Printf 类函数作为参数传递出来了。 最终目标是创建一个自定义日志记录功能,可以注入其他假定日志记录的方法。所以,我学会了如何使用 kprintf 。但是如何将其结果传递给callstack。 有人可以帮我制作以下代码吗?
open System
type logging () =
let logWarning =
let logToConsole msg = Console.WriteLine("WARN: {0} {1}", DateTime.Now, msg)
fun fmt -> Printf.kprintf logToConsole fmt
let doThingsWithLogging warningLogger =
warningLogger "%s %d %f" "DoThingsWithLogger" 3 3.29
warningLogger "%d %A" 3 "DoThingsAgain"
member __.RunTest() =
logWarning "%s %d %f" "String, int, float" 12 38.8
logWarning "%d %f %s" 83 128.9 "int, float, string"
doThingsWithLogging logWarning
let test = logging()
test.RunTest ()
如果您尝试在FSI中运行它,您将立即看到问题出在哪里 - 在 warningLogger 参数上键入推断不允许编译对此函数的第二次调用。 我怎样才能使它工作,我可以使用 warningLogger 作为普通的 printf 类型的函数? 非常感谢你提前。
答案 0 :(得分:3)
通常,F#不允许您将泛型函数作为参数传递。这在您的示例中并不容易看到(因为格式字符串更棘手),但您可以在以下更简单的情况下看到:
let foo f =
f 1
f 1.0
没有办法告诉编译器参数f
应该是泛型函数'a -> unit
,所以这不会编译。
您示例中最简单的解决方案可能是定义一个具有通用LogWraning
方法的类型,然后传递该类型的实例。像这样:
type Logger() =
member x.LogWarning fmt =
let logMessage msg = Console.WriteLine("WARN: {0} {1}", DateTime.Now, msg)
Printf.kprintf logMessage fmt
let doThingsWithLogging (logger:Logger) =
logger.LogWarning "%s %d %f" "DoThingsWithLogger" 3 3.29
logger.LogWarning "%d %A" 3 "DoThingsAgain"
doThingsWithLogging (Logger())