F#,sprintf“%A”在被歧视的联盟中的表现

时间:2014-07-02 14:00:18

标签: f#

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

2 个答案:

答案 0 :(得分:5)

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

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

答案 1 :(得分: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 )