我想知道是否有一种很好的方法来定义一个函数xoco70/kendo-tournaments
,它接受一个函数captureOutput
,该函数可能包含print语句并返回f
打印的任何内容。如,
f
我在想,也许有一种很好的方法可以与let f x = print "%s" x
let op = captureOutput (f "Hello World")
val op : string = "Hello World"
异步地进行此操作,但我无法解决任何问题。
干杯
编辑:
根据Fyodor Soikin的评论,以下代码可以满足我的需求:
Console.ReadLine()
答案 0 :(得分:5)
您可以通过Console.SetOut
临时替换标准输出编写器。
但要注意:此替换也会影响在其他线程上执行的代码并捕获其输出,并与函数的输出混合。这基本上就是所谓的“黑客”。
如果这只是一个非常小的实用工具,永远不会变得更复杂,那么这很好。但这永远不应成为生产系统的一部分。如果你正在开发复杂的东西的一部分,我建议改变函数本身,通过打印功能对其进行参数化:
type Printer = abstract member print (fmt: StringFormat<'T, unit>) : 'T
let captureOutput f =
let mutable output = ""
let print s = output <- output + s
f { new Printer with member _.print fmt = kprintf print fmt }
output
let f x (p: Printer) = p.print "%s" x
let op = captureOutput (f "Hello World")
(这个例子必须使用一个接口,因为没有它,print
函数会失去通用性)
答案 1 :(得分:3)
实施@FyodorSoikin的建议(我只是在之后看到我写了这个):
let captureOutput f =
use writer = new StringWriter()
use restoreOut =
let origOut = Console.Out
{ new IDisposable with member __.Dispose() = Console.SetOut origOut }
Console.SetOut writer
f ()
writer.ToString ()
let f x () = printf "%s" x
let op = captureOutput (f "Hello World")
(Nb必须将额外的参数添加到f
以便可以部分应用 - captureOutput
必须采用函数,而不是值。)
IDisposable
的对象表达式用于包装清理,以便对f
的调用是异常安全的。