Wie kann ich Ausgabe eines benutzerdefinierten Typ anpassen printf?
-
16-09-2019 - |
Frage
Ich habe durch ein gutes Stück von lesen Expert F # und arbeite eine tatsächliche Anwendung auf den Aufbau. Während des Debuggens habe ich vorbei fsi Befehle wie diese daran gewöhnt, Dinge lesbar im ers Fenster zu machen:
fsi.AddPrinter(fun (x : myType) -> myType.ToString())
Ich möchte dies erweitern mit dem printf Formatierungsprogramm zu arbeiten, so konnte ich beispiel geben.
printf "%A" instanceOfMyType
und die Ausgabe für einen benutzerdefinierten Typen steuern. Das Buch setzt voraus, dass diese (S. 93 getan werden kann, „Generic Struktur Formatierung erweitert werden kann mit beliebigen benutzerdefinierten Datentypen zu arbeiten, ein Thema auf der F # Website "genannt), aber ich habe versagen alle Verweise zu finden, wie zu dies tatsächlich zu erreichen. Wer weiß, wie? Ist es überhaupt möglich?
Edit:
Ich sollte ein Codebeispiel enthalten sind, ist es eine Satzart, die ich mit zu tun habe, z.
type myType =
{a: int}
override m.ToString() = "hello"
let t = {a=5}
printfn "%A" t
printfn "%A" (box t)
beide Druck Aussagen ergeben:
{a = 5;}
Lösung
Es ist wie der richtige Weg sieht diese 2.0 in F # zu tun ist, mithilfe des StructuredFormatDisplay
Attribut, zum Beispiel:
[<StructuredFormatDisplay("hello {a}")>]
type myType = {a: int}
In diesem Beispiel wird anstelle des Standard-{a = 42;}
, würden Sie hello 42
erhalten.
Dies funktioniert auf die gleiche Art und Weise für das Objekt, aufnehmen und Union-Typen. Und obwohl muss das Muster des Formats "PreText {PropertyName} PostText"
sein ( PRETEXT und PostText ist optional), ist dies tatsächlich mächtiger als ToString()
weil:
-
PropertyName
kann eine Eigenschaft von jeder Art sein. Wenn es nicht ein String ist, dann wird es auch für strukturierte Formatierung unterliegen. Don Syme Blog gibt ein Beispiel rekursiv einen Baum auf diese Weise zu formatieren. -
Es kann eine berechnete Eigenschaft sein. So könnten Sie tatsächlich bekommen
ToString()
für die Aufzeichnung und Union-Typen zu arbeiten, wenn auch in eher Umwegen:[<StructuredFormatDisplay("{AsString}")>] type myType = {a: int} override m.ToString() = "hello" member m.AsString = m.ToString() // a property that calls a method
Durch die Art und Weise, ToString()
wird immer dann verwendet werden (auch für die Aufzeichnung und Union-Typen), wenn Sie printfn "%O"
rufen statt printfn "%A"
.
Andere Tipps
Hmm ... Ich erinnere mich vage, einige Änderungen, aber ich vergessen, wenn sie vor oder nach dem CTP (1.9.6.2) passiert ist.
Auf jedem Fall auf der CTP, ich sehe, dass
type MyType() =
override this.ToString() = "hi"
let x = new MyType()
let xs = Array.create 25 x
printfn "%A" x
printfn "%A" xs
, wenn im VFSI Fenster ausgewertet tut, was ich möchte, und dass
x;;
xs;;
druckt auch schön. Also, ich denke, ich bin unklar, wie dies von dem abweicht, was gewünscht wird?
Wenn Sie ToString-Methode außer Kraft setzen, sollte das tun.