Pemformatan teks biasa
F# mendukung pemformatan teks biasa yang diperiksa jenisnya menggunakan printf
, printfn
, sprintf
, dan fungsi terkait.
Contohnya,
dotnet fsi
> printfn "Hello %s, %d + %d is %d" "world" 2 2 (2+2);;
memberikan output
Hello world, 2 + 2 is 4
F# juga memungkinkan nilai terstruktur untuk diformat sebagai teks biasa. Misalnya, perhatikan contoh berikut yang memformat output sebagai tampilan tuple seperti matriks.
dotnet fsi
> printfn "%A" [ for i in 1 .. 5 -> [ for j in 1 .. 5 -> (i, j) ] ];;
[[(1, 1); (1, 2); (1, 3); (1, 4); (1, 5)];
[(2, 1); (2, 2); (2, 3); (2, 4); (2, 5)];
[(3, 1); (3, 2); (3, 3); (3, 4); (3, 5)];
[(4, 1); (4, 2); (4, 3); (4, 4); (4, 5)];
[(5, 1); (5, 2); (5, 3); (5, 4); (5, 5)]]
Pemformatan teks biasa terstruktur diaktifkan jika Anda menggunakan format %A
dalam string pemformatan printf
.
Ini juga diaktifkan saat memformat output nilai dalam interaktif F#, yang output-nya menyertakan informasi tambahan dan juga dapat disesuaikan.
Pemformatan teks biasa juga dapat diamati melalui panggilan apa pun ke x.ToString()
pada nilai rekaman dan gabungan F#, termasuk yang terjadi secara implisit dalam penelusuran kesalahan, pengelogan, dan peralatan lainnya.
Memeriksa string format-printf
Kesalahan waktu kompilasi akan dilaporkan jika fungsi pemformatan printf
digunakan dengan argumen yang tidak cocok dengan penentu format printf dalam string format. Contohnya,
sprintf "Hello %s" (2+2)
memberikan output
sprintf "Hello %s" (2+2)
----------------------^
stdin(3,25): error FS0001: The type 'string' does not match the type 'int'
Secara teknis, saat menggunakan printf
dan fungsi terkait lainnya, aturan khusus dalam kompilator F# memeriksa harfiah string yang diteruskan sebagai string format, memastikan argumen berikutnya yang diterapkan adalah jenis yang benar agar sesuai dengan penentu format yang digunakan.
Penentu format untuk printf
Spesifikasi format untuk format printf
adalah string dengan penanda %
yang menunjukkan format. Tempat penampung format terdiri dari %[flags][width][.precision][type]
yang jenisnya ditafsirkan sebagai berikut:
Penentu format | Jenis | Keterangan |
---|---|---|
%b |
bool Aku akan menemuinya.System.Boolean |
Diformat sebagai true atau false |
%s |
string Aku akan menemuinya.System.String |
Diformat sebagai isinya yang tidak lolos |
%c |
char Aku akan menemuinya.System.Char |
Diformat sebagai karakter harfiah |
%d , %i |
jenis bilangan bulat dasar | Diformat sebagai bilangan bulat desimal, ditandatangani jika jenis bilangan bulat dasar ditandatangani |
%u |
jenis bilangan bulat dasar | Diformat sebagai bilangan bulat desimal tidak bertanda |
%x , %X |
jenis bilangan bulat dasar | Diformat sebagai angka heksadesimal tidak bertanda (a-f atau A-F untuk masing-masing digit heksa) |
%o |
jenis bilangan bulat dasar | Diformat sebagai bilangan oktal tidak bertanda |
%B |
jenis bilangan bulat dasar | Diformat sebagai bilangan biner tidak bertanda |
%e , %E |
jenis floating point dasar | Diformat sebagai nilai bertanda yang memiliki bentuk [-]d.dddde[sign]ddd di mana d adalah satu digit desimal, dddd adalah satu atau lebih digit desimal, ddd tepat tiga digit desimal, dan tanda adalah + atau - |
%f , %F |
jenis floating point dasar | Diformat sebagai nilai bertanda yang memiliki bentuk [-]dddd.dddd , di mana dddd adalah satu atau lebih digit desimal. Jumlah digit sebelum titik desimal tergantung pada besarnya angka, dan jumlah digit setelah titik desimal tergantung pada presisi yang diminta. |
%g , %G |
jenis floating point dasar | Diformat menggunakan sebagai nilai bertanda yang dicetak dalam format %f atau %e , mana saja yang lebih ringkas untuk nilai dan presisi yang diberikan. |
%M |
nilai decimal (System.Decimal ) |
Diformat menggunakan penentu format "G" untuk System.Decimal.ToString(format) |
%O |
nilai apa pun | Diformat dengan boxing objek dan memanggil metode System.Object.ToString() -nya |
%A |
nilai apa pun | Diformat menggunakan pemformatan teks biasa terstruktur dengan pengaturan tata letak default |
%a |
nilai apa pun | Memerlukan dua argumen: fungsi pemformatan yang menerima parameter konteks dan nilainya, dan nilai tertentu untuk dicetak |
%t |
nilai apa pun | Memerlukan satu argumen: fungsi pemformatan yang menerima parameter konteks yang menghasilkan atau mengembalikan teks yang sesuai |
%% |
(tidak ada) | Tidak memerlukan argumen dan mencetak tanda persen biasa: % |
Jenis bilangan bulat dasar adalah byte
(System.Byte
), sbyte
(System.SByte
), int16
(System.Int16
), uint16
(System.UInt16
), int32
(System.Int32
), uint32
(System.UInt32
), int64
(System.Int64
), uint64
(System.UInt64
), nativeint
(System.IntPtr
), dan unativeint
(System.UIntPtr
).
Jenis floating point dasar adalah float
(System.Double
), float32
(System.Single
), dan decimal
(System.Decimal
).
Lebar opsional adalah bilangan bulat yang menunjukkan lebar minimal dari hasil. Misalnya, %6d
mencetak bilangan bulat, mengawalinya dengan spasi untuk mengisi setidaknya enam karakter. Jika lebar adalah *
, argumen bilangan bulat tambahan diambil untuk menentukan lebar yang sesuai.
Bendera yang valid adalah:
Bendera | Efek |
---|---|
0 |
Menambahkan nol sebagai ganti dari spasi untuk membuat lebar yang diperlukan |
- |
Rata kiri hasil dalam lebar yang ditentukan |
+ |
Menambahkan karakter + jika angkanya positif (untuk mencocokkan tanda - untuk negatif) |
karakter spasi | Menambahkan spasi tambahan jika angkanya positif (untuk mencocokkan tanda '-' untuk negatif) |
Bendera printf #
tidak valid dan kesalahan waktu kompilasi akan dilaporkan jika digunakan.
Nilai diformat menggunakan kultur invarian. Pengaturan kultur tidak relevan dengan pemformatan printf
kecuali jika memengaruhi hasil pemformatan %O
dan %A
. Untuk informasi selengkapnya, lihat pemformatan teks biasa terstruktur.
Pemformatan %A
Penentu format %A
digunakan untuk memformat nilai dengan cara yang dapat dibaca manusia, dan juga dapat berguna untuk melaporkan informasi diagnostik.
Nilai primitif
Saat memformat teks biasa menggunakan penentu %A
, nilai numerik F# diformat dengan sufiks dan kultur invarian. Nilai floating point diformat menggunakan 10 tempat presisi floating point. Contohnya,
printfn "%A" (1L, 3n, 5u, 7, 4.03f, 5.000000001, 5.0000000001)
menghasilkan
(1L, 3n, 5u, 7, 4.03000021f, 5.000000001, 5.0)
Saat menggunakan penentu %A
, string diformat menggunakan tanda kutip. Kode escape tidak ditambahkan dan sebagai gantinya karakter mentah dicetak. Contohnya,
printfn "%A" ("abc", "a\tb\nc\"d")
menghasilkan
("abc", "a b
c"d")
Nilai .NET
Saat memformat teks biasa menggunakan penentu %A
, objek .NET non-F# diformat dengan menggunakan x.ToString()
menggunakan pengaturan default .NET yang diberikan oleh System.Globalization.CultureInfo.CurrentCulture
dan System.Globalization.CultureInfo.CurrentUICulture
. Contohnya,
open System.Globalization
let date = System.DateTime(1999, 12, 31)
CultureInfo.CurrentCulture <- CultureInfo.GetCultureInfo("de-DE")
printfn "Culture 1: %A" date
CultureInfo.CurrentCulture <- CultureInfo.GetCultureInfo("en-US")
printfn "Culture 2: %A" date
menghasilkan
Culture 1: 31.12.1999 00:00:00
Culture 2: 12/31/1999 12:00:00 AM
Nilai terstruktur
Saat memformat teks biasa menggunakan penentu %A
, indentasi blok digunakan untuk daftar dan tuple F#. Ini ditunjukkan dalam contoh sebelumnya.
Struktur array juga digunakan, termasuk array multidimensi. Array satu dimensi ditampilkan dengan sintaksis [| ... |]
. Contohnya,
printfn "%A" [| for i in 1 .. 20 -> (i, i*i) |]
menghasilkan
[|(1, 1); (2, 4); (3, 9); (4, 16); (5, 25); (6, 36); (7, 49); (8, 64); (9, 81);
(10, 100); (11, 121); (12, 144); (13, 169); (14, 196); (15, 225); (16, 256);
(17, 289); (18, 324); (19, 361); (20, 400)|]
Lebar cetak default adalah 80. Lebar ini dapat disesuaikan dengan menggunakan lebar cetak dalam penentu format. Contohnya,
printfn "%10A" [| for i in 1 .. 5 -> (i, i*i) |]
printfn "%20A" [| for i in 1 .. 5 -> (i, i*i) |]
printfn "%50A" [| for i in 1 .. 5 -> (i, i*i) |]
menghasilkan
[|(1, 1);
(2, 4);
(3, 9);
(4, 16);
(5, 25)|]
[|(1, 1); (2, 4);
(3, 9); (4, 16);
(5, 25)|]
[|(1, 1); (2, 4); (3, 9); (4, 16); (5, 25)|]
Menentukan lebar cetak 0 menghasilkan tidak ada lebar cetak yang digunakan. Satu baris teks akan dihasilkan, kecuali string yang disematkan dalam output berisi jeda baris. Misalnya
printfn "%0A" [| for i in 1 .. 5 -> (i, i*i) |]
printfn "%0A" [| for i in 1 .. 5 -> "abc\ndef" |]
menghasilkan
[|(1, 1); (2, 4); (3, 9); (4, 16); (5, 25)|]
[|"abc
def"; "abc
def"; "abc
def"; "abc
def"; "abc
def"|]
Batas kedalaman 4 digunakan untuk nilai urutan (IEnumerable
), yang ditampilkan sebagai seq { ...}
. Batas kedalaman 100 digunakan untuk nilai daftar dan array.
Contohnya,
printfn "%A" (seq { for i in 1 .. 10 -> (i, i*i) })
menghasilkan
seq [(1, 1); (2, 4); (3, 9); (4, 16); ...]
Indentasi blok juga digunakan untuk struktur rekaman publik dan nilai gabungan. Contohnya,
type R = { X : int list; Y : string list }
printfn "%A" { X = [ 1;2;3 ]; Y = ["one"; "two"; "three"] }
menghasilkan
{ X = [1; 2; 3]
Y = ["one"; "two"; "three"] }
Jika %+A
digunakan, struktur privat dari rekaman dan gabungan juga diungkapkan dengan menggunakan refleksi. Misalnya
type internal R =
{ X : int list; Y : string list }
override _.ToString() = "R"
let internal data = { X = [ 1;2;3 ]; Y = ["one"; "two"; "three"] }
printfn "external view:\n%A" data
printfn "internal view:\n%+A" data
menghasilkan
external view:
R
internal view:
{ X = [1; 2; 3]
Y = ["one"; "two"; "three"] }
Nilai besar, siklik, atau sangat berlapis
Nilai terstruktur besar diformat ke jumlah node objek keseluruhan maksimum 10000.
Nilai yang sangat berlapis diformat hingga kedalaman 100. Dalam kedua kasus ...
digunakan untuk menghilangkan beberapa output. Contohnya,
type Tree =
| Tip
| Node of Tree * Tree
let rec make n =
if n = 0 then
Tip
else
Node(Tip, make (n-1))
printfn "%A" (make 1000)
menghasilkan output yang besar dengan beberapa bagian yang dihilangkan:
Node(Tip, Node(Tip, ....Node (..., ...)...))
Siklus terdeteksi dalam grafik objek dan ...
digunakan di tempat yang siklusnya terdeteksi. Misalnya
type R = { mutable Links: R list }
let r = { Links = [] }
r.Links <- [r]
printfn "%A" r
menghasilkan
{ Links = [...] }
Nilai lazy, null, dan fungsi
Nilai lazy dicetak sebagai Value is not created
atau teks yang setara jika nilainya belum dievaluasi.
Nilai null dicetak sebagai null
kecuali jika jenis nilai statik ditentukan sebagai jenis gabungan di mana null
adalah representasi yang diizinkan.
Nilai fungsi F# dicetak sebagai nama penutupan yang dibuat secara internal, misalnya, <fun:it@43-7>
.
Menyesuaikan pemformatan teks biasa dengan StructuredFormatDisplay
Saat menggunakan penentu %A
, keberadaan atribut StructuredFormatDisplay
pada deklarasi jenis akan dipatuhi. Ini dapat digunakan untuk menentukan teks pengganti dan properti untuk menampilkan nilai. Misalnya:
[<StructuredFormatDisplay("Counts({Clicks})")>]
type Counts = { Clicks:int list}
printfn "%20A" {Clicks=[0..20]}
menghasilkan
Counts([0; 1; 2; 3;
4; 5; 6; 7;
8; 9; 10; 11;
12; 13; 14;
15; 16; 17;
18; 19; 20])
Menyesuaikan pemformatan teks biasa dengan mengambil alih ToString
Penerapan default dari ToString
dapat diamati dalam pemrograman F#. Seringkali, hasil default tidak cocok untuk digunakan baik dalam tampilan informasi yang berhubungan dengan programmer atau output pengguna, dan akibatnya adalah hal yang umum untuk mengambil alih penerapan default.
Secara default, jenis rekaman dan gabungan F# mengambil alih penerapan ToString
dengan penerapan yang menggunakan sprintf "%+A"
. Contohnya,
type Counts = { Clicks:int list }
printfn "%s" ({Clicks=[0..10]}.ToString())
menghasilkan
{ Clicks = [0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10] }
Untuk jenis kelas, tidak ada penerapan default ToString
yang disediakan dan default .NET digunakan, yang melaporkan nama jenis. Contohnya,
type MyClassType(clicks: int list) =
member _.Clicks = clicks
let data = [ MyClassType([1..5]); MyClassType([1..5]) ]
printfn "Default structured print gives this:\n%A" data
printfn "Default ToString gives:\n%s" (data.ToString())
menghasilkan
Default structured print gives this:
[MyClassType; MyClassType]
Default ToString gives:
[MyClassType; MyClassType]
Menambahkan pengambilalihan untuk ToString
dapat memberikan pemformatan yang lebih baik.
type MyClassType(clicks: int list) =
member _.Clicks = clicks
override _.ToString() = sprintf "MyClassType(%0A)" clicks
let data = [ MyClassType([1..5]); MyClassType([1..5]) ]
printfn "Now structured print gives this:\n%A" data
printfn "Now ToString gives:\n%s" (data.ToString())
menghasilkan
Now structured print gives this:
[MyClassType([1; 2; 3; 4; 5]); MyClassType([1; 2; 3; 4; 5])]
Now ToString gives:
[MyClassType([1; 2; 3; 4; 5]); MyClassType([1; 2; 3; 4; 5])]
Menyesuaikan pemformatan teks biasa dengan StructuredFormatDisplay
dan ToString
Untuk mencapai pemformatan yang konsisten untuk penentu format %A
dan %O
, gabungkan penggunaan StructuredFormatDisplay
dengan pengambilalihan ToString
. Contohnya,
[<StructuredFormatDisplay("{DisplayText}")>]
type MyRecord =
{
a: int
}
member this.DisplayText = this.ToString()
override _.ToString() = "Custom ToString"
Mengevaluasi definisi berikut
let myRec = { a = 10 }
let myTuple = (myRec, myRec)
let s1 = sprintf $"{myRec}"
let s2 = sprintf $"{myTuple}"
let s3 = sprintf $"%A{myTuple}"
let s4 = sprintf $"{[myRec; myRec]}"
let s5 = sprintf $"%A{[myRec; myRec]}"
memberikan teks
val myRec: MyRecord = Custom ToString
val myTuple: MyRecord * MyRecord = (Custom ToString, Custom ToString)
val s1: string = "Custom ToString"
val s2: string = "(Custom ToString, Custom ToString)"
val s3: string = "(Custom ToString, Custom ToString)"
val s4: string = "[Custom ToString; Custom ToString]"
val s5: string = "[Custom ToString; Custom ToString]"
Penggunaan StructuredFormatDisplay
dengan properti DisplayText
pendukung berarti fakta bahwa myRec
adalah jenis rekaman struktural diabaikan selama pencetakan terstruktur, dan pengambilalihan ToString()
lebih disukai dalam semua keadaan.
Penerapan antarmuka System.IFormattable
dapat ditambahkan untuk penyesuaian lebih lanjut dengan adanya spesifikasi format .NET.
Pencetakan terstruktur F# Interactive
F# Interactive (dotnet fsi
) menggunakan versi ekstensi dari pemformatan teks biasa terstruktur untuk melaporkan nilai dan memungkinkan penyesuaian tambahan. Untuk informasi selengkapnya, lihat F# Interactive.
Menyesuaikan tampilan debug
Debugger untuk .NET mematuhi penggunaan atribut seperti DebuggerDisplay
dan DebuggerTypeProxy
, dan ini memengaruhi tampilan terstruktur objek di jendela pemeriksaan debugger.
Kompilator F# secara otomatis menghasilkan atribut ini untuk jenis gabungan dan rekaman terdiskriminasi, tetapi bukan jenis kelas, antarmuka, atau struktur.
Atribut ini diabaikan dalam pemformatan teks biasa F#, tetapi akan berguna untuk menerapkan metode ini untuk meningkatkan tampilan saat men-debug jenis F#.
Lihat juga
Saran dan Komentar
https://aka.ms/ContentUserFeedback.
Segera hadir: Sepanjang tahun 2024 kami akan menghentikan penggunaan GitHub Issues sebagai mekanisme umpan balik untuk konten dan menggantinya dengan sistem umpan balik baru. Untuk mengetahui informasi selengkapnya, lihat:Kirim dan lihat umpan balik untuk