F#Interactive - 当后者可枚举时,如何使其打印对象的属性

boh*_*nko 3 f# f#-interactive

在示例中显示更容易.如果我将以下内容发送给F#interactive

type Person = {Name : string; Age : int}
let joe = {Name = "Joe"; Age=30}
Run Code Online (Sandbox Code Playgroud)

输出是:

type Person =
  {Name: string;
   Age: int;}
val joe : Person = {Name = "Joe";
                    Age = 30;}
Run Code Online (Sandbox Code Playgroud)

Fsi非常聪明,可以打印所有属性.

逐行发送以下内容

let l = new List<int>()
l
Run Code Online (Sandbox Code Playgroud)

结果是

val l : List<int>
val it : List<int> = seq []
Run Code Online (Sandbox Code Playgroud)

Fsi看到了这个l实现IEnumerable,并且(正确地)认为这是我期望看到的.但也有其他的属性l,特别是CountCapacity.(这对于列表来说并不重要,但在我的情况下它适用于复杂类型)

如何使F#交互式打印出对象的属性并忽略它IEnumerable(就像Person第一个例子中的类型一样)

Tom*_*cek 7

您可以使用自定义打印机fsi.AddPrinter.它需要一个指定如何格式化特定类型的函数 - 我不认为有一种简单的方法可以执行此操作,但IEnumerable在这种情况下您可以使用非泛型.下面使用默认打印打印序列并添加Count:

fsi.AddPrinter(fun (en:System.Collections.IEnumerable) -> 
  let count = Seq.cast<obj> en |> Seq.length
  sprintf "%A { Count = %d }" en count
)
Run Code Online (Sandbox Code Playgroud)

例如:

> l;;
val it : List<int> = seq [] { Count = 0 }
> seq { 1 .. 100000 };;
val it : seq<int> = seq [1; 2; 3; 4; ...] { Count = 100000 }
Run Code Online (Sandbox Code Playgroud)

有趣的是,这也改变了字符串的打印,但是只有当envalue不是string类型时才可以通过添加自定义属性来避免这种情况.

> "hello";;
val it : string = "hello" { Count = 5 }
Run Code Online (Sandbox Code Playgroud)