如何使用printf自定义自定义类型的输出? [英] How do I customize output of a custom type using printf?
问题描述
我已经阅读了很多 Expert F#并正在构建一个实际的应用程序.调试时,我已经习惯于传递这样的fsi命令以使内容在repl窗口中清晰可见:
I've read through a good chunk of Expert F# and am working on building an actual application. While debugging, I've grown accustomed to passing fsi commands like this to make things legible in the repl window:
fsi.AddPrinter(fun (x : myType) -> myType.ToString())
我想将此扩展到与printf格式化程序一起使用,所以我可以输入例如.
I would like to extend this to work with the printf formatter, so I could type e.g.
printf "%A" instanceOfMyType
并控制自定义类型的输出.该书暗示可以做到这一点(第93页,通用结构格式可以扩展为可与任何用户定义的数据类型一起使用, F#网站上涵盖的一个主题"),但我没有找到有关如何实际完成此操作的任何参考.有人知道如何吗?甚至有可能吗?
and control the output for a custom type. The book implies that this can be done (p 93, "Generic structural formatting can be extended to work with any user-defined data types, a topic covered on the F# website"), but I have failed to find any references as to how to actually accomplish this. Does anyone know how? Is it even possible?
我应该包括一个代码示例,它是我正在处理的一种记录类型,例如
I should have included a code sample, it's a record type that I'm dealing with, e.g.
type myType =
{a: int}
override m.ToString() = "hello"
let t = {a=5}
printfn "%A" t
printfn "%A" (box t)
两个打印语句均产生:
{a = 5;}
推荐答案
It looks like the Right Way to do this in F# 2.0 is by using the StructuredFormatDisplay
attribute, for example:
[<StructuredFormatDisplay("hello {a}")>]
type myType = {a: int}
在此示例中,您将获得hello 42
,而不是默认的{a = 42;}
.
In this example, instead of the default {a = 42;}
, you would get hello 42
.
对于对象,记录和联合类型,其工作方式相同.尽管模式必须为"PreText {PropertyName} PostText"
格式( PreText 和 PostText 是可选的),但实际上它比ToString()
更强大,因为:
This works the same way for object, record, and union types. And although the pattern must be of the format "PreText {PropertyName} PostText"
(PreText and PostText being optional), this is actually more powerful than ToString()
because:
PropertyName
can be a property of any type. If it is not a string, then it will also be subject to structured formatting. Don Syme's blog gives an example of recursively formatting a tree in this way.
它可能是计算所得的属性.因此,您实际上可以使ToString()
适用于记录和联合类型,尽管采用的是一种相当简单的方法:
It may be a calculated property. So you could actually get ToString()
to work for record and union types, though in a rather round-about way:
[<StructuredFormatDisplay("{AsString}")>]
type myType =
{a: int}
override m.ToString() = "hello"
member m.AsString = m.ToString() // a property that calls a method
顺便说一句,如果您调用printfn "%O"
而不是printfn "%A"
,则将始终使用ToString()
(甚至用于记录和联合类型).
By the way, ToString()
will always be used (even for record and union types) if you call printfn "%O"
instead of printfn "%A"
.
这篇关于如何使用printf自定义自定义类型的输出?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!