F# Interactive技巧:在sprintf/printf/fprintf中使用AddPrinter,addPrintTransformer和%A来格式化数据

Mingtian Ni 问过这样的一个问题:

我想改变一些类型在fsi输出中的格式,尤其是集合类型。怎样的方法才是比较合理的呢?….有哪位朋友可以提供一点信息吗? 或者一些指南和示例那就更好了。

下面就是一些在F#Interactive中格式化数据的技巧。 这并不足以理解为一个指南,这仅仅能帮你入门。如果你需要更多的示例,请联系我。

对F# interactive来说,一个简单的方法就是使用fsi.AddPrintTransformer来生成一个显示对象的替代品(或者使用更小的、产生一个字符串的fsi.AddPrinter函数),例如:

type C(elems:int list) =

   member x.Contents = elems

   member x.IsBig = elems.Length > 100

let c = C [1;2;3] 

fsi.AddPrintTransformer (fun (c:C) -> box c.Contents) 

产生:

val  c  :  C  =  [1;  2;  3] 

AddprintTransformer有一点很好,你可以让它成为有条件的——返回null 来表明formatter(用来格式化的一串字符)应该被忽略:

fsi.AddPrintTransformer (fun (c:C) -> if c.IsBig then null else box c.Contents)

有一点非常好,如果你将它和“obj”类型一起使用,你可以对任意的对象作特定的格式化:

fsi.AddPrintTransformer (fun (obj:obj) -> match obj with :? C as c -> box c.Contents | _ -> null)

这里有一个问题,fsi.AddPrinter和fsi.AddPrintTransformer不会更改位于sprintf、printf等函数中的%A的行为。对于那些设置一个简单标志(即命名一个成员属性产生一个代理对象)而受限制的类型,以及一些周围的文字:

[<StructuredFormatDisplayAttribute("CCC {Contents}")>]

type C(elems:int list) =

   member x.Contents = elems

 

let c = C [1;2;3]

产生:

val c : C = CCC [1; 2; 3]

如果你的类型是一个普通的集合类, 那么使用一个list 或者sequence 作为这个替代对象。

如果你的类型是一个matirx或者table 类型,那么使用一个2D array作为这个替代对象。

如果你的类型在逻辑上说是一个union 类型,但你已经隐藏了其背后的抽象边界的表现形式,那么可以考虑使用一个独立的、能够解开你的对象的结构的helper union 类型(如:如果你的类型是一个递归类型,那么可以解开它的第一层)

如果你的数据是递归树型的,你可以描述它的子树为一个list:

[<StructuredFormatDisplayAttribute("Tree {Contents}")>]

type Tree(node: int, elems: Tree list) =

   member x.Contents = (node, elems)

 

let c = Tree (1, [ Tree (2, []); Tree (3, [ Tree (4, []) ]) ])

let c2 = Tree (1, [ c; c])

let c3 = Tree (1, [ c2; c2])

产生令人舒适的结果:

val c3 : Tree =

  Tree (1,

        [Tree (1,

               [Tree (1, [Tree (2, []); Tree (3, [Tree (4, [])])]);

                Tree (1, [Tree (2, []); Tree (3, [Tree (4, [])])])]);

         Tree (1,

               [Tree (1, [Tree (2, []); Tree (3, [Tree (4, [])])]);

                Tree (1, [Tree (2, []); Tree (3, [Tree (4, [])])])])])

 

通常,你也应该考虑实现ToString方法,如果你还经常使用VS debugger,也应该考虑添加一个DebuggerDisplay属性.

原文链接:http://blogs.msdn.com/b/dsyme/archive/2010/01/08/some-tips-and-tricks-for-formatting-data-in-f-interactive-and-a-in-sprintf-printf-fprintf.aspx

posted @ 2011-12-31 10:32  tryfsharp  阅读(215)  评论(0编辑  收藏  举报