Как настроить вывод настраиваемого типа с помощью printf?
Я прочитал хороший кусок Expert F # и работаю над созданием реального приложения. Во время отладки я привык передавать команды fsi, подобные этому, чтобы сделать текст разборчивым в окне repl:
fsi.AddPrinter(fun (x : myType) -> myType.ToString())
Я хотел бы расширить это, чтобы работать с форматом printf, поэтому я мог бы напечатать, например.
printf "%A" instanceOfMyType
и управлять выходом для пользовательского типа. Из книги следует, что это можно сделать (стр. 93, "Общее структурное форматирование может быть расширено для работы с любыми определенными пользователем типами данных,
тема, затронутая на веб-сайте F # "), но я не нашел ссылок на то, как это сделать. Кто-нибудь знает, как это возможно?
Edit:
Я должен был включить образец кода, это тип записи, с которым я имею дело, например
type myType =
{a: int}
override m.ToString() = "hello"
let t = {a=5}
printfn "%A" t
printfn "%A" (box t)
оба вывода print дают:
{a = 5;}
Ответы
Ответ 1
Похоже, что правильный способ сделать это в F # 2.0 - это использовать атрибут StructuredFormatDisplay
, например:
[<StructuredFormatDisplay("hello {a}")>]
type myType = {a: int}
В этом примере вместо стандартного {a = 42;}
вы получите hello 42
.
Это работает одинаково для типов объектов, записей и соединений. И хотя шаблон должен иметь формат "PreText {PropertyName} PostText"
(PreText и PostText необязательны), это на самом деле более мощное, чем ToString()
, потому что:
-
PropertyName
может быть свойством любого типа. Если это не строка, она также будет подвергнута структурированному форматированию. Блог Don Syme дает пример рекурсивного форматирования дерева таким образом.
-
Это может быть вычисленное свойство. Таким образом, вы действительно можете получить ToString()
для работы с типами записей и объединений, хотя и довольно круто:
[<StructuredFormatDisplay("{AsString}")>]
type myType =
{a: int}
override m.ToString() = "hello"
member m.AsString = m.ToString() // a property that calls a method
Кстати, ToString()
всегда будет использоваться (даже для типов записей и объединений), если вы вызываете printfn "%O"
вместо printfn "%A"
.
Ответ 2
Хм... Я смутно вспоминаю некоторые изменения в этом, но я забыл, что они произошли до или после CTP (1.9.6.2).
В любом случае, на CTP, я вижу, что
type MyType() =
override this.ToString() = "hi"
let x = new MyType()
let xs = Array.create 25 x
printfn "%A" x
printfn "%A" xs
при оценке в окне VFSI делает то, что я хочу, и что
x;;
xs;;
также хорошо печатает. Итак, я не понимаю, насколько это отличается от желаемого?
Ответ 3
Если вы переопределите метод ToString, это должно сделать.