在f#中捕获print语句

ira*_*ira 5 f#

我想知道是否有一种很好的方法来定义一个函数captureOutput,该函数接受一个f可能包含print语句的函数并返回f打印的内容.例如,

let f x = print "%s" x
let op = captureOutput (f "Hello World")

val op : string = "Hello World"
Run Code Online (Sandbox Code Playgroud)

我在想,或许有一种很好的方法可以异步地做到这一点,Console.ReadLine()但我还没有能够解决任何问题.

干杯

编辑:

根据Fyodor Soikin的评论,下面的代码做了我想要的:

let captureOutput f x =
    let newOut = new IO.StringWriter()
    Console.SetOut(newOut)
    f x
    Console.SetOut(Console.Out)
    newOut.ToString()
Run Code Online (Sandbox Code Playgroud)

Fyo*_*kin 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") 
Run Code Online (Sandbox Code Playgroud)

(这个例子必须使用一个接口,因为没有它,该print功能将失去通用性)