24

F#中以下两个语句有什么区别?它们之间有什么优点或缺点(不包括明显的语法差异)?

我知道 WriteLine() 是 .NET 的一部分,但不明白这可能会产生什么影响。

示例代码:

printfn "This is an integer: %d" 5
System.Console.WriteLine("This is an integer: {0}" , 5)
4

4 回答 4

38

printfn它的各种表亲有几个优点:

  • 它们更短
  • 他们可以做一些静态类型检查;即printfn "%d" "bad type"不会编译。
  • ...但您不必进行静态类型检查;%O打印任何对象
  • 他们可以打印诸如数组、元组和可区分联合之类的“智能”表示%A
  • 它们可以部分应用;ieprintfn "%d, %d" 3是一个有效的表达式。这特别漂亮,因为编译器可以检查您在以后使用此子表达式时是否实际应用了正确数量的参数 - 不像Console.WriteLine它会愉快地接受太多或太少的参数。

在实践中,最常见的部分应用很可能只包含格式字符串;例如

let printParticle = printfn "Particle at (%d, %d), state %A, p = %f"

printParticle 2 3 //compile time warning about ignored value
printParticle 3 4 someState 0.4 //fine
printParticle 5 6 someState 0.4 0.7 //compile-time error

但是,在 F# 3.1 之前,它也很慢。它的速度足以跟上您的编码器,但是如果您以某种形式的序列化使用它,它可能会变成瓶颈。F# 3.1 发布公告(作为 Visual Studio 2013的一部分分发)声称可以显着提高性能,但我尚未对此进行验证。

就个人而言,我通常使用 printfn 进行探索性编码,然后我主要坚持%A使用偶尔引入的其他说明符。但是,.NET 原生字符串格式在某些情况下仍然有用,因为它具有详细的文化和与格式相关的选项。如果您想要最大速度直接连接(或 a StringBuilder)将很容易胜过两者,因为这避免了解释格式字符串。

于 2013-06-12T18:11:55.217 回答
7

以下是printf-like 函数与Console.WriteLine.

优点:

  • printfn函数是类型安全的:

    printfn "This is an integer: %i" 5 // works
    printfn "This is an integer: %i" "5" // doesn't compile
    
  • 使用 进行部分应用很容易,但由于重载次数过多printfn,情况并非如此:Console.WriteLine

    [1; 2; 3] |> List.iter (printfn "%i; ")
    
  • printfn通过说明符更好地支持 F# 类型%A

缺点:

除了不能像@mydogisbox 提到的那样重用参数之外, -likeprintfn函数Console.WriteLine(由于使用反射)慢得多;您不应该将前者用于记录目的。

于 2013-06-12T18:08:01.360 回答
4

printfn 函数可以部分应用。

let printDouble = printfn "%f"
printDouble 2.0

由于标准 .NET 函数将元组作为 F# 中的参数,因此您不能在其中使用部分应用程序。

printfn 的第二个优点是可以输入参数。所以这不会编译:

let printDouble = printfn "%d"
printDouble 2.0
于 2013-06-12T18:07:30.373 回答
4

除了样式,System.Console.WriteLine还有可以重用参数的优点,即System.Console.WriteLine("This is a integer twice: {0} {0}", 5)

此外,正如这里printfn所指出的,您可以使用您无法使用的 F# 对象进行漂亮的打印,System.Console.WriteLine并且由于它不需要元组,因此您可以使用它进行部分应用程序。

正如其他人所指出的,printfn使用反射,因此明显慢于PrintLine,但也是类型安全的。

于 2013-06-12T17:51:16.683 回答