如何编写一个 fprintfn 函数,在每次写入时打开、追加、关闭文件,而不会出现 ObjectDisposedException?
How can I write an fprintfn function that opens, appends, closes the file on each write, without getting an ObjectDisposedException?
TL;DR:如何编写类似 fprintfn
的函数来访问和关闭文件,其行为类似于 printf
系列函数,但不会抛出 ObjectDisposedException
关于多个参数?
作为一个方便的嵌入函数,我发现自己写了下面的代码,运行了一段时间:
let fprintfn a b =
use handle = File.AppendText("somelogfile.log")
printfn a b |> ignore // write to stdout
fprintfn handle a b // write to logfile
// works
fprintfn "Here we are, %i years of age" 42
// throws ObjectDisposedException
fprintfn "Here we are, %i years of age in $i" 42 DateTime.Now.Year
无论我使用 use
还是 using
并且参数数量超过 2 时都会引发错误。
经过一番摸索之后,我得出结论,只要我将上面的新 fprintfn
函数与多个打印格式参数一起使用,它就会创建一个闭包。这在某种程度上似乎是有意义的,尽管在你 return 明确关闭的情况下更隐蔽(即 return 访问 handle
的实际 fun x -> something
变量)。
现在的问题是:如何重写上述语句,同时保留原始 fprintfn
函数使用和语法的便利性,而不让它抛出 ObjectDisposedException
?
PS:编写上述函数的首选方法是使用以下方法,它允许所有 fprintfn
语法,但是当您使用单个打印时,它会抛出相同的异常格式参数。
let fprintfn a =
use handle = File.AppendText("somelogfile.log")
printfn a |> ignore
fprintfn handle a
fprintf "Test" // works
fprintf "Test: %i" 42 // throws ODE
你是对的 fprintf
创建了一个延续并 returns 它,所以当你调用那个延续时,文件已经关闭了。
但您可以更深入地使用 kprintf
。它允许您提供 a "continuation" - 即接收格式化字符串并对其执行任何操作的函数。
let fprintfn a =
let doPrint s =
use handle = File.AppendText("somelogfile.log")
printfn "%s" s
fprintfn handle "%s" s
kprintf doPrint a
然后,当然,您可以使用 File.AppendAllText
:
稍微简化一下
let fprintfn a =
let doPrint s =
File.AppendAllText("somelogfile.log", s + "\n")
printfn "%s" s
kprintf doPrint a
TL;DR:如何编写类似 fprintfn
的函数来访问和关闭文件,其行为类似于 printf
系列函数,但不会抛出 ObjectDisposedException
关于多个参数?
作为一个方便的嵌入函数,我发现自己写了下面的代码,运行了一段时间:
let fprintfn a b =
use handle = File.AppendText("somelogfile.log")
printfn a b |> ignore // write to stdout
fprintfn handle a b // write to logfile
// works
fprintfn "Here we are, %i years of age" 42
// throws ObjectDisposedException
fprintfn "Here we are, %i years of age in $i" 42 DateTime.Now.Year
无论我使用 use
还是 using
并且参数数量超过 2 时都会引发错误。
经过一番摸索之后,我得出结论,只要我将上面的新 fprintfn
函数与多个打印格式参数一起使用,它就会创建一个闭包。这在某种程度上似乎是有意义的,尽管在你 return 明确关闭的情况下更隐蔽(即 return 访问 handle
的实际 fun x -> something
变量)。
现在的问题是:如何重写上述语句,同时保留原始 fprintfn
函数使用和语法的便利性,而不让它抛出 ObjectDisposedException
?
PS:编写上述函数的首选方法是使用以下方法,它允许所有 fprintfn
语法,但是当您使用单个打印时,它会抛出相同的异常格式参数。
let fprintfn a =
use handle = File.AppendText("somelogfile.log")
printfn a |> ignore
fprintfn handle a
fprintf "Test" // works
fprintf "Test: %i" 42 // throws ODE
你是对的 fprintf
创建了一个延续并 returns 它,所以当你调用那个延续时,文件已经关闭了。
但您可以更深入地使用 kprintf
。它允许您提供 a "continuation" - 即接收格式化字符串并对其执行任何操作的函数。
let fprintfn a =
let doPrint s =
use handle = File.AppendText("somelogfile.log")
printfn "%s" s
fprintfn handle "%s" s
kprintf doPrint a
然后,当然,您可以使用 File.AppendAllText
:
let fprintfn a =
let doPrint s =
File.AppendAllText("somelogfile.log", s + "\n")
printfn "%s" s
kprintf doPrint a