【问题标题】:F#, Performance of sprintf "%A" on Discriminated UnionsF#,sprintf "%A" 在可区分联合上的性能
【发布时间】:2014-07-02 14:00:18
【问题描述】:

DU 有许多非常有用的方面,包括内置的漂亮打印。然而,令我惊讶的是,我的简单 ToString 函数使格式化 DU 的速度提高了 1000 倍以上。我错过了什么吗? sprintf "%A" 比我的 ToString 函数做得更多?

type XYZ = 
    |X of float 
    |Y of float*float 
    |Z

let ar = // some test Array
    [| for i in 1..3000 do for a in [ X(1.) ; Y(2.,3.) ; Z ] do yield a |] 

let xyzToString (x:XYZ) = 
    match x with
    |X (a)  -> sprintf "X %.1f" a
    |Y (a,b)-> sprintf "Y (%.1f,%.1f)" a b       
    |Z      -> "Z"

#time
ar|> Array.map (fun x -> sprintf "%s" (xyzToString x) )  // about   15 ms
ar|> Array.map (fun x -> sprintf "%A" x )                // about 4000 ms

【问题讨论】:

标签: f#


【解决方案1】:

sprintf "%A" 在运行时做一些reflection 以确定正在打印的对象的类型和结构,这非常耗时。

您的版本在编译时绑定到特定类型 (XYZ),从而提高效率。

【讨论】:

    【解决方案2】:

    正如@Mau 所指出的,您的比较不是苹果对苹果。 printf 接受任何类型的参数。您的函数接受一个已知类型。

    如果这对您来说是一个真正的问题,并且您有兴趣更简洁地封装解决方案,您可以执行以下操作:

    type XYZ = 
        |X of float 
        |Y of float*float 
        |Z
    
        override this.ToString() =
            match this with
            |X (a)  -> sprintf "X %.1f" a
            |Y (a,b)-> sprintf "Y (%.1f,%.1f)" a b       
            |Z      -> "Z"
    
    ...
    
    ar|> Array.map (fun x -> sprintf "%O" x )
    

    【讨论】:

      猜你喜欢
      • 2011-11-19
      • 1970-01-01
      • 1970-01-01
      • 2017-12-27
      • 2020-04-30
      • 1970-01-01
      • 2013-08-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多