Pencocokan Pola
Pola adalah aturan untuk mengubah data input. Pola digunakan di seluruh F# untuk membandingkan data dengan struktur atau struktur logis, menguraikan data menjadi bagian-bagian penyusunnya, atau mengekstrak informasi dari data dengan berbagai cara.
Keterangan
Pola digunakan dalam banyak konstruksi bahasa pemrograman, seperti ekspresi match
. Pola digunakan saat Anda memproses argumen untuk fungsi dalam pengikatan let
, ekspresi lambda, dan dalam penanganan pengecualian yang berkaitan dengan ekspresi try...with
. Untuk informasi selengkapnya, lihat Ekspresi Pencocokan, le Bindings, Ekspresi Lambda: Kata kuncifun
, dan Pengecualian: Ekspresi try...with
.
Misalnya, dalam ekspresi match
, polanya adalah apa yang mengikuti simbol pipa.
match expression with
| pattern [ when condition ] -> result-expression
...
Setiap pola bertindak sebagai aturan untuk mengubah input dengan cara tertentu. Dalam ekspresi match
, setiap pola diperiksa secara bergantian untuk melihat apakah data input kompatibel dengan pola tersebut. Jika kecocokan ditemukan, ekspresi hasil akan dijalankan. Jika kecocokan tidak ditemukan, aturan pola selanjutnya akan diuji. Opsional ketika bagian kondisi dijelaskan dalam Ekspresi Pencocokan.
Pola yang didukung ditunjukkan dalam tabel berikut. Pada durasi, input diuji terhadap setiap pola berikut dalam urutan yang tercantum di dalam tabel dan pola diterapkan secara rekursif, dari pertama hingga terakhir saat mereka muncul dalam kode Anda dan dari kiri ke kanan untuk pola di setiap baris.
Nama | Deskripsi | Contoh |
---|---|---|
Pola konstanta | Setiap harfiah numerik, karakter, atau string, konstanta enumerasi, atau pengidentifikasi harfiah yang ditentukan | 1.0 , , "test" 30 ,Color.Red |
Pola pengidentifikasi | Nilai kasus dari discriminated union, label pengecualian, atau kasus pola aktif | Some(x) Failure(msg) |
Pola variabel | identifier | a |
Pola as |
pola sebagai pengidentifikasi | (a, b) as tuple1 |
Pola OR | pola1 | pola2 | ([h] | [h; _]) |
Pola AND | pattern1 & pattern2 | (a, b) & (_, "test") |
Pola kontra | pengidentifikasi :: pengidentifikasi-daftar | h :: t |
Pola daftar | [ pola_1; ... ; pola_n ] | [ a; b; c ] |
Pola array | [| pola_1; ..; pola_n |] | [| a; b; c |] |
Pola tanda kurung | ( pola ) | ( a ) |
Pola tuple | ( pola_1, ... , pola_n ) | ( a, b ) |
Pola rekaman | { pengidentifikasi1 = pola_1; ... ; pengidentifikasi_n = pola_n } | { Name = name; } |
Pola wildcard | _ | _ |
Pola bersama dengan anotasi jenis | pola : jenis | a : int |
Pola pengujian jenis | :? jenis [ sebagai pengidentifikasi ] | :? System.DateTime as dt |
Pola null | nihil | null |
Pola nameof | nameof expr | nameof str |
Pola Konstanta
Pola konstanta adalah harfiah numerik, karakter, dan string, konstanta enumerasi (dengan nama jenis enumerasi disertakan). Ekspresi match
yang hanya memiliki pola konstanta dapat dibandingkan dengan pernyataan kasus dalam bahasa pemrograman lain. Input dibandingkan dengan nilai harfiah dan polanya cocok jika nilainya sama. Jenis harfiah harus kompatibel dengan jenis input.
Contoh berikut mendemonstrasikan 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 yang didasarkan pada konstanta enumerasi. Anda harus menentukan nama jenis enumerasi ketika 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, formulir pengidentifikasi menentukan bagaimana pola dicocokkan. Jika pengidentifikasi lebih panjang daripada karakter tunggal dan dimulai dengan karakter huruf besar, kompilator akan mencoba untuk mencocokkan dengan pola pengenal. Pengidentifikasi untuk pola ini dapat berupa nilai yang ditandai dengan atribut Literal, kasus discriminated union, pengidentifikasi pengecualian, atau kasus pola aktif. Jika tidak ditemukan pengidentifikasi yang cocok, pencocokan gagal dan aturan pola berikutnya, pola variabel, dibandingkan dengan input.
Pola discriminated union dapat berupa kasus bernama sederhana atau mereka dapat memiliki nilai atau tuple yang berisi beberapa nilai. Jika terdapat nilai, Anda harus menentukan pengidentifikasi untuk nilai tersebut. Dalam kasus tuple, Anda harus memberikan pola tuple pengidentifikasi untuk setiap elemen tupel atau pengidentifikasi dengan nama bidang untuk satu atau beberapa bidang union bernama. Lihat contoh kode di bagian ini untuk contoh.
Jenis option
adalah discriminated union yang memiliki dua kasus, yaitu 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 berkaitan dengan kasus Some
, tetapi None
harus muncul dengan sendirinya. Dalam kode berikut, variabel var1
diberikan nilai yang diperoleh dengan mencocokkannya dengan kasus Some
.
let printOption (data : int option) =
match data with
| Some var1 -> printfn "%d" var1
| None -> ()
Dalam contoh berikut, discriminated union PersonName
berisi campuran string dan karakter yang mewakili kemungkinan formulir nama. Kasus-kasus discriminated union 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 discriminated union yang memiliki bidang bernama, Anda menggunakan tanda sama dengan (=) untuk mengekstrak nilai bidang bernama. Misalnya, pertimbangkan discriminated union dengan deklarasi seperti berikut.
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, Circle(r)
dan 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 merupakan sebuah pengecualian digunakan dalam pencocokan pola dalam konteks penanganan pengecualian. Untuk informasi tentang pencocokan pola dalam pengaturan pengecualian, lihat Pengecualian: try...with
Ekspresi.
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 di dalam pola lain, sehingga mengaktifkan struktur yang lebih kompleks, seperti tuple dan array untuk diurai menjadi variabel.
Contoh berikut mendemonstrasikan pola variabel di dalam pola tuple.
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)
Pola as
Pola as
adalah pola yang memiliki klausul as
yang ditambahkan padanya. Klausul as
mengikat nilai yang cocok ke nama yang dapat digunakan dalam ekspresi eksekusi dari ekspresi match
, atau, dalam kasus di mana pola ini digunakan dalam pengikatan let
, nama tersebut ditambahkan sebagai pengikatan ke cakupan 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 cocok dengan beberapa pola dan Anda ingin menjalankan kode yang sama sebagai hasilnya. Jenis kedua sisi pola OR harus kompatibel.
Contoh berikut mendemonstrasikan 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 adalah seperti detectZeroTuple
yang ditunjukkan dalam 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 Kontra
Pola kontra digunakan untuk menguraikan daftar menjadi elemen pertama kepala, dan daftar yang berisi elemen yang tersisa ekornya.
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 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 Array
Pola array menyerupai pola daftar dan dapat digunakan untuk menguraikan 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 Tanda Kurung
Tanda kurung dapat dikelompokkan di sekitar pola untuk mencapai asosiativitas yang diinginkan. Dalam contoh berikut, tanda kurung digunakan untuk mengontrol asosiativitas 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 cocok dengan input dalam formulir tuple dan memungkinkan tuple diurai menjadi elemen penyusunnya dengan menggunakan variabel pencocokan pola untuk setiap posisi dalam tuple.
Contoh berikut mendemonstrasikan pola tuple dan juga menggunakan pola harfiah, 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 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 Wildcard
Pola wildcard diwakili oleh karakter garis bawah (_
) dan cocok dengan input apa pun, sama seperti pola variabel, kecuali bahwa input dibuang alih-alih ditetapkan ke variabel. Pola wildcard sering digunakan dalam pola lain sebagai tempat penampung untuk nilai yang tidak dibutuhkan dalam ekspresi di sebelah kanan simbol ->
. Pola wildcard juga sering digunakan di akhir daftar pola untuk mencocokkan input yang tidak cocok. Pola wildcard didemonstrasikan dalam banyak contoh kode dalam topik ini. Lihat kode sebelumnya sebagai salah satu contoh.
Pola yang Memiliki Anotasi Jenis
Pola dapat memiliki anotasi jenis. Mereka berperilaku seperti anotasi jenis lain dan memandu inferensi seperti anotasi jenis lainnya. Tanda kurung dibutuhkan di sekitar anotasi jenis dalam pola. Kode berikut menunjukkan pola yang memiliki anotasi jenis.
let detect1 x =
match x with
| 1 -> printfn "Found a 1!"
| (var1 : int) -> printfn "%d" var1
detect1 0
detect1 1
Pola Pengujian Jenis
Pola pengujian jenis digunakan untuk mencocokkan input dengan sebuah tipe. Jika jenis input cocok dengan (atau merupakan tipe turunan dari) tipe yang ditentukan dalam pola, pencocokan berhasil.
Contoh berikut mendemonstrasikan 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 sebuah pengidentifikasi merupakan tipe turunan tertentu, Anda tidak membutuhkan 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 Null
Pola null cocok dengan nilai null yag dapat muncul saat Anda bekerja dengan jenis yang memungkinkan nilai null. Pola null sering digunakan saat berinteroperasi dengan kode .NET Framework. Misalnya, nilai pengembalian dari API .NET mungkin merupakan input ke ekspresi match
. Anda dapat mengontrol aliran program berdasarkan apakah nilai pengembaliannya adalah null dan juga berdasarkan karakteristik lain dari nilai pengembalian. Anda dapat menggunakan pola null untuk mencegah nilai null menyebar ke seluruh 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 nameof
Pola nameof
cocok dengan string ketika nilainya sama dengan ekspresi yang mengikuti kata kunci nameof
. contohnya:
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
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