Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Pola adalah aturan untuk mengubah data input. Mereka digunakan di seluruh F# untuk membandingkan data dengan struktur atau struktur logis, menguraikan data menjadi bagian konstituen, atau mengekstrak informasi dari data dengan berbagai cara.
Komentar
Pola digunakan dalam banyak konstruksi bahasa, seperti ekspresi match
. Mereka digunakan saat Anda memproses argumen untuk fungsi dalam pengikatan let
, ekspresi lambda, dan dalam handler pengecualian yang terkait dengan ekspresi try...with
. Untuk informasi selengkapnya, lihat Ekspresi Kecocokan, Pengikatan let, Ekspresi Lambda: Kata Kunci fun
, dan Pengecualian: Ekspresi try...with
.
Misalnya, dalam ekspresi match
, pola adalah apa yang mengikuti simbol pipa.
match expression with
| pattern [ when condition ] -> result-expression
...
Setiap pola bertindak sebagai aturan untuk mengubah input dalam beberapa cara. Dalam ekspresi match
, setiap pola diperiksa pada gilirannya untuk melihat apakah data input kompatibel dengan pola. Jika kecocokan ditemukan, ekspresi hasil dijalankan. Jika kecocokan tidak ditemukan, aturan pola berikutnya akan diuji. Bagian opsional ketika kondisi dijelaskan pada Ekspresi Pencocokan .
Pola yang didukung diperlihatkan dalam tabel berikut. Pada waktu proses, input diuji terhadap setiap pola berikut dalam urutan yang tercantum dalam tabel, dan pola diterapkan secara rekursif, dari pertama hingga terakhir saat muncul dalam kode Anda, dan dari kiri ke kanan untuk pola pada setiap baris.
Nama | Deskripsi | Contoh |
---|---|---|
Pola konstanta | Setiap literal numerik, karakter, atau string, konstanta enumerasi, atau pengidentifikasi literal yang sudah ditentukan |
1.0 , "test" , 30 , Color.Red |
Pola pengidentifikasi | Nilai kasus dari gabungan yang diskriminasi, label pengecualian, atau kasus pola aktif | Some(x) Failure(msg) |
Pola variabel | pengidentifikasi | a |
pola as |
pola sebagai pengidentifikasi | (a, b) as tuple1 |
Pola OR | pola1 | pola2 | ([h] | [h; _]) |
Pola AND | pola 1 & pola2 | (a, b) & (_, "test") |
Pola kontra | pengidentifikasi :: pengidentifikasi daftar | h :: t |
Pola daftar | [ pattern_1; ... ; pattern_n ] | [ a; b; c ] |
Pola larik | [| pattern_1; ..; pattern_n |] | [| a; b; c |] |
Pola yang dikurung | ( pola ) | ( a ) |
Pola tupel | ( pattern_1, ... , pattern_n ) | ( a, b ) |
Pola rekaman | { pengidentifikasi1 = pattern_1; ... ; identifier_n = pattern_n } | { Name = name; } |
Pola karakter pengganti | _ | _ |
Pola bersama dengan anotasi tipe | pola : jenis | a : int |
Pola uji tipe | :? ketik [ sebagai pengidentifikasi ] | :? System.DateTime as dt |
Pola kosong | nol | null |
Pola nama | daluwarsa | nameof str |
Pola Konstanta
Konstanta termasuk literal numerik, karakter, dan string, serta konstanta enumerasi (termasuk nama tipe enumerasi). Ekspresi match
yang hanya memiliki pola konstan dapat dibandingkan dengan pernyataan kasus dalam bahasa lain. Input dibandingkan dengan nilai harfiah dan pola cocok jika nilainya sama. Jenis literal harus sesuai dengan tipe masukan.
Contoh berikut menunjukkan penggunaan pola harfiah, dan juga menggunakan pola variabel dan pola OR.
[<Literal>]
let Three = 3
let filter123 x =
match x with
// The following line contains literal patterns combined with an OR pattern.
| 1 | 2 | Three -> printfn "Found 1, 2, or 3!"
// The following line contains a variable pattern.
| var1 -> printfn "%d" var1
for x in 1..10 do filter123 x
Contoh lain dari pola harfiah adalah pola berdasarkan konstanta enumerasi. Anda harus menentukan nama jenis enumerasi saat Anda menggunakan konstanta enumerasi.
type Color =
| Red = 0
| Green = 1
| Blue = 2
let printColorName (color:Color) =
match color with
| Color.Red -> printfn "Red"
| Color.Green -> printfn "Green"
| Color.Blue -> printfn "Blue"
| _ -> ()
printColorName Color.Red
printColorName Color.Green
printColorName Color.Blue
Pola Pengidentifikasi
Jika pola adalah rangkaian karakter yang membentuk pengidentifikasi yang valid, bentuk pengidentifikasi menentukan bagaimana pola dicocokkan. Jika pengidentifikasi lebih panjang dari satu karakter dan dimulai dengan karakter huruf besar, pengkompilasi mencoba membuat kecocokan dengan pola pengidentifikasi. Pengidentifikasi untuk pola ini bisa menjadi nilai yang ditandai dengan atribut Literal, kasus gugus dibedakan, pengidentifikasi pengecualian, atau kasus pola aktif. Jika tidak ada pengidentifikasi yang cocok yang ditemukan, kecocokan gagal dan aturan pola berikutnya, pola variabel, dibandingkan dengan input.
Pola penyatuan yang diskriminasi dapat berupa kasus bernama sederhana atau dapat memiliki nilai, atau tuple yang berisi beberapa nilai. Jika ada nilai, Anda harus menentukan pengidentifikasi untuk nilai tersebut. Dalam kasus tuple, Anda harus menyediakan pola tuple dengan pengidentifikasi untuk setiap elemen tuple atau pengidentifikasi dengan nama bidang untuk satu atau beberapa bidang serikat bernama. Lihat contoh kode di bagian ini misalnya.
Jenis option
adalah serikat terdiskriminasi yang memiliki dua kasus, Some
dan None
. Satu kasus (Some
) memiliki nilai, tetapi yang lain (None
) hanyalah kasus bernama. Oleh karena itu, Some
perlu memiliki variabel untuk nilai yang terkait dengan kasus Some
, tetapi None
harus muncul dengan sendirinya. Dalam kode berikut, variabel var1
diberi nilai yang diperoleh dengan mencocokkan dengan kasus Some
.
let printOption (data : int option) =
match data with
| Some var1 -> printfn "%d" var1
| None -> ()
Dalam contoh berikut, PersonName
adalah sebuah penyatuan yang didiskriminasi, berisi campuran string dan karakter yang mewakili bentuk nama yang mungkin. Kasus-kasus dari union diskriminatif adalah FirstOnly
, LastOnly
, dan FirstLast
.
type PersonName =
| FirstOnly of string
| LastOnly of string
| FirstLast of string * string
let constructQuery personName =
match personName with
| FirstOnly(firstName) -> printf "May I call you %s?" firstName
| LastOnly(lastName) -> printf "Are you Mr. or Ms. %s?" lastName
| FirstLast(firstName, lastName) -> printf "Are you %s %s?" firstName lastName
Untuk serikat terdiskriminasi yang memiliki bidang bernama, Anda menggunakan tanda sama dengan (=) untuk mengekstrak nilai bidang bernama. Misalnya, pertimbangkan serikat yang didiskriminasi dengan deklarasi seperti berikut ini.
type Shape =
| Rectangle of height : float * width : float
| Circle of radius : float
Anda dapat menggunakan bidang bernama dalam ekspresi pencocokan pola sebagai berikut.
let matchShape shape =
match shape with
| Rectangle(height = h) -> printfn $"Rectangle with length %f{h}"
| Circle(r) -> printfn $"Circle with radius %f{r}"
Penggunaan bidang bernama bersifat opsional, jadi dalam contoh sebelumnya, baik Circle(r)
maupun Circle(radius = r)
memiliki efek yang sama.
Saat Anda menentukan beberapa bidang, gunakan titik koma (;) sebagai pemisah.
match shape with
| Rectangle(height = h; width = w) -> printfn $"Rectangle with height %f{h} and width %f{w}"
| _ -> ()
Pola aktif memungkinkan Anda menentukan pencocokan pola kustom yang lebih kompleks. Untuk informasi selengkapnya tentang pola aktif, lihat Pola Aktif.
Kasus di mana pengidentifikasi yang merupakan pengecualian digunakan dalam pencocokan pola dalam konteks penanganan pengecualian. Untuk informasi tentang pencocokan pola dalam penanganan pengecualian, lihat Pengecualian : Ekspresi try...with
.
Pola Variabel
Pola variabel menetapkan nilai yang dicocokkan dengan nama variabel, yang kemudian tersedia untuk digunakan dalam ekspresi eksekusi di sebelah kanan simbol ->
. Pola variabel saja cocok dengan input apa pun, tetapi pola variabel sering muncul dalam pola lain, sehingga memungkinkan struktur kompleks seperti tuple dan array untuk dipecah menjadi variabel.
Contoh berikut menunjukkan pola variabel dalam pola tupal.
let function1 x =
match x with
| (var1, var2) when var1 > var2 -> printfn "%d is greater than %d" var1 var2
| (var1, var2) when var1 < var2 -> printfn "%d is less than %d" var1 var2
| (var1, var2) -> printfn "%d equals %d" var1 var2
function1 (1,2)
function1 (2, 1)
function1 (0, 0)
sebagai pola
Pola as
adalah pola yang memiliki klausa as
ditambahkan ke dalamnya. Klausa as
mengikat nilai yang cocok ke sebuah nama yang dapat digunakan dalam ekspresi eksekusi dari ekspresi match
, atau, dalam kasus di mana pola ini digunakan dalam suatu pengikatan let
, nama tersebut ditambahkan sebagai pengikatan ke ruang lingkup lokal.
Contoh berikut menggunakan pola as
.
let (var1, var2) as tuple1 = (1, 2)
printfn "%d %d %A" var1 var2 tuple1
Pola OR
Pola OR digunakan ketika data input dapat mencocokkan beberapa pola, dan Anda ingin menjalankan kode yang sama sebagai hasilnya. Jenis kedua sisi pola OR harus kompatibel.
Contoh berikut menunjukkan pola OR.
let detectZeroOR point =
match point with
| (0, 0) | (0, _) | (_, 0) -> printfn "Zero found."
| _ -> printfn "Both nonzero."
detectZeroOR (0, 0)
detectZeroOR (1, 0)
detectZeroOR (0, 10)
detectZeroOR (10, 15)
Pola AND
Pola AND mengharuskan input cocok dengan dua pola. Jenis kedua sisi pola AND harus kompatibel.
Contoh berikut seperti detectZeroTuple
ditampilkan di bagian Pola Tuple nanti dalam topik ini, tetapi di sini var1
dan var2
diperoleh sebagai nilai dengan menggunakan pola AND.
let detectZeroAND point =
match point with
| (0, 0) -> printfn "Both values zero."
| (var1, var2) & (0, _) -> printfn "First value is 0 in (%d, %d)" var1 var2
| (var1, var2) & (_, 0) -> printfn "Second value is 0 in (%d, %d)" var1 var2
| _ -> printfn "Both nonzero."
detectZeroAND (0, 0)
detectZeroAND (1, 0)
detectZeroAND (0, 10)
detectZeroAND (10, 15)
Pola Kekurangan
Pola kontra digunakan untuk menguraikan daftar ke dalam elemen pertama, kepala , dan daftar yang berisi elemen yang tersisa, ekor .
let list1 = [ 1; 2; 3; 4 ]
// This example uses a cons pattern and a list pattern.
let rec printList l =
match l with
| head :: tail -> printf "%d " head; printList tail
| [] -> printfn ""
printList list1
Pola Daftar
Pola daftar memungkinkan daftar diurai menjadi sejumlah elemen. Pola daftar itu sendiri hanya dapat mencocokkan daftar sejumlah elemen tertentu.
// This example uses a list pattern.
let listLength list =
match list with
| [] -> 0
| [ _ ] -> 1
| [ _; _ ] -> 2
| [ _; _; _ ] -> 3
| _ -> List.length list
printfn "%d" (listLength [ 1 ])
printfn "%d" (listLength [ 1; 1 ])
printfn "%d" (listLength [ 1; 1; 1; ])
printfn "%d" (listLength [ ] )
Pola Larik
Pola array menyerupai pola daftar dan dapat digunakan untuk mengurai array dengan panjang tertentu.
// This example uses array patterns.
let vectorLength vec =
match vec with
| [| var1 |] -> var1
| [| var1; var2 |] -> sqrt (var1*var1 + var2*var2)
| [| var1; var2; var3 |] -> sqrt (var1*var1 + var2*var2 + var3*var3)
| _ -> failwith (sprintf "vectorLength called with an unsupported array size of %d." (vec.Length))
printfn "%f" (vectorLength [| 1. |])
printfn "%f" (vectorLength [| 1.; 1. |])
printfn "%f" (vectorLength [| 1.; 1.; 1.; |])
printfn "%f" (vectorLength [| |] )
Pola Yang Dikurung
Tanda kurung dapat dikelompokkan di sekitar pola untuk mencapai asokiativitas yang diinginkan. Dalam contoh berikut, tanda kurung digunakan untuk mengontrol associativity antara pola AND dan pola kontra.
let countValues list value =
let rec checkList list acc =
match list with
| (elem1 & head) :: tail when elem1 = value -> checkList tail (acc + 1)
| head :: tail -> checkList tail acc
| [] -> acc
checkList list 0
let result = countValues [ for x in -10..10 -> x*x - 4 ] 0
printfn "%d" result
Pola Tuple
Pola tuple mencocokkan input dalam bentuk tuple dan memungkinkan tuple diuraikan menjadi elemen-elemen konstituennya dengan menggunakan variabel pola pencocokan untuk setiap posisi dalam tuple.
Contoh berikut menunjukkan pola tuple dan juga menggunakan pola literal, pola variabel, dan pola wildcard.
let detectZeroTuple point =
match point with
| (0, 0) -> printfn "Both values zero."
| (0, var2) -> printfn "First value is 0 in (0, %d)" var2
| (var1, 0) -> printfn "Second value is 0 in (%d, 0)" var1
| _ -> printfn "Both nonzero."
detectZeroTuple (0, 0)
detectZeroTuple (1, 0)
detectZeroTuple (0, 10)
detectZeroTuple (10, 15)
Pola Rekaman
Pola rekaman digunakan untuk mengurai rekaman untuk mengekstrak nilai bidang. Pola tidak harus mereferensikan semua bidang rekaman; setiap bidang yang dihilangkan hanya tidak berpartisipasi dalam pencocokan dan tidak diekstraksi.
// This example uses a record pattern.
type MyRecord = { Name: string; ID: int }
let IsMatchByName record1 (name: string) =
match record1 with
| { MyRecord.Name = nameFound; MyRecord.ID = _; } when nameFound = name -> true
| _ -> false
let recordX = { Name = "Parker"; ID = 10 }
let isMatched1 = IsMatchByName recordX "Parker"
let isMatched2 = IsMatchByName recordX "Hartono"
Pola KartuBebas
Pola wildcard diwakili oleh karakter underscore (_
) dan cocok dengan input apa pun, sama seperti pola variabel, kecuali input tersebut dibuang alih-alih ditetapkan ke variabel. Pola wildcard sering digunakan dalam pola lain sebagai placeholder untuk nilai yang tidak diperlukan dalam ekspresi di sebelah kanan simbol ->
. Pola wildcard juga sering digunakan di akhir daftar pola untuk memadankan input yang tidak terpadankan. Pola karakter pengganti ditampilkan dalam banyak contoh kode di topik ini. Lihat kode sebelumnya untuk satu contoh.
Pola yang Memiliki Anotasi Tipe
Pola dapat memiliki anotasi jenis. Ini berulah seperti anotasi jenis lain dan memandu inferensi seperti anotasi jenis lainnya. Tanda kurung diperlukan di sekitar anotasi jenis dalam pola. Kode berikut menunjukkan pola yang memiliki anotasi tipe.
let detect1 x =
match x with
| 1 -> printfn "Found a 1!"
| (var1 : int) -> printfn "%d" var1
detect1 0
detect1 1
Pola Uji Tipe
Pola pengujian jenis digunakan untuk mencocokkan input terhadap jenis. Jika jenis input cocok dengan (atau jenis turunan) jenis yang ditentukan dalam pola, kecocokan berhasil.
Contoh berikut menunjukkan pola pengujian jenis.
open System.Windows.Forms
let RegisterControl(control:Control) =
match control with
| :? Button as button -> button.Text <- "Registered."
| :? CheckBox as checkbox -> checkbox.Text <- "Registered."
| _ -> ()
Jika Anda hanya memeriksa apakah pengidentifikasi memiliki jenis turunan tertentu, Anda tidak memerlukan bagian as identifier
dari pola, seperti yang ditunjukkan dalam contoh berikut:
type A() = class end
type B() = inherit A()
type C() = inherit A()
let m (a: A) =
match a with
| :? B -> printfn "It's a B"
| :? C -> printfn "It's a C"
| _ -> ()
Pola Nol
Pola null cocok dengan nilai null yang dapat muncul saat Anda bekerja dengan tipe yang memungkinkan nilai null. Pola null sering digunakan saat beroperasi dengan kode .NET Framework. Misalnya, nilai pengembalian .NET API mungkin merupakan input ke ekspresi match
. Anda dapat mengontrol alur program berdasarkan apakah nilai pengembalian null, dan juga pada karakteristik lain dari nilai yang dikembalikan. Anda dapat menggunakan pola null untuk mencegah nilai null menyebar ke sisa program Anda.
Contoh berikut menggunakan pola null dan pola variabel.
let ReadFromFile (reader : System.IO.StreamReader) =
match reader.ReadLine() with
| null -> printfn "\n"; false
| line -> printfn "%s" line; true
let fs = System.IO.File.Open("..\..\Program.fs", System.IO.FileMode.Open)
let sr = new System.IO.StreamReader(fs)
while ReadFromFile(sr) = true do ()
sr.Close()
Pola null juga direkomendasikan untuk kemampuan nullability F# 9 :
let len (str: string | null) =
match str with
| null -> -1
| s -> s.Length
Demikian pula, Anda dapat menggunakan pola baru khusus terkait nullability :
let let str = // str is inferred to be `string | null`
match str with
| Null -> -1
| NonNull (s: string) -> s.Length
Nama pola
Pola nameof
cocok dengan string saat nilainya sama dengan ekspresi yang mengikuti kata kunci nameof
. misalnya:
let f (str: string) =
match str with
| nameof str -> "It's 'str'!"
| _ -> "It is not 'str'!"
f "str" // matches
f "asdf" // does not match
Lihat operator nameof
untuk informasi tentang nama yang dapat Anda ambil.
Lihat juga
- Cocokkan Ekspresi
- Pola Aktif
- Referensi Bahasa F#