Desen Eşleştirme
Desenler, giriş verilerini dönüştürme kurallarıdır. F# genelinde verileri mantıksal bir yapı veya yapıyla karşılaştırmak, verileri bileşen parçalara ayırmak veya verilerden çeşitli yollarla bilgi ayıklamak için kullanılır.
Açıklamalar
Desenler, ifade gibi birçok dil yapısında match
kullanılır. Bağlamalardaki, lambda ifadelerindeki let
ve ifadeyle try...with
ilişkili özel durum işleyicilerindeki işlevler için bağımsız değişkenleri işlerken kullanılırlar. Daha fazla bilgi için bkz. İfadeleri Eşleştir, Bağlamalar, Lambda İfadeleri: Anahtar fun
Sözcük ve Özel Durumlar: İfadetry...with
.
Örneğin, ifadede match
desen, boru simgesini izleyen desendir.
match expression with
| pattern [ when condition ] -> result-expression
...
Her desen, girişi bir şekilde dönüştürmek için bir kural işlevi görür. İfadede match
her desen sırayla incelenerek giriş verilerinin desenle uyumlu olup olmadığını görebilirsiniz. Eşleşme bulunursa sonuç ifadesi yürütülür. Eşleşme bulunmazsa, sonraki desen kuralı test edilir. koşul bölümü İfadeleri Eşleştir bölümünde açıklandığında isteğe bağlı.
Desteklenen desenler aşağıdaki tabloda gösterilmiştir. Çalışma zamanında, giriş aşağıdaki desenlerin her birinde tabloda listelenen sırayla test edilir ve desenler, kodunuzda göründükleri sırada ilkten sona ve her satırdaki desenler için soldan sağa doğru yinelemeli olarak uygulanır.
Veri Akışı Adı | Açıklama | Örnek |
---|---|---|
Sabit desen | Herhangi bir sayısal, karakter veya dize değişmez değeri, sabit listesi sabiti veya tanımlı değişmez değer tanımlayıcısı | 1.0 , "test" , 30 , Color.Red |
Tanımlayıcı deseni | Ayrımcı bir birleşimin, özel durum etiketinin veya etkin desen büyük/küçük harf durumunun büyük/küçük harf değeri | Some(x) Failure(msg) |
Değişken deseni | identifier | a |
as Desen |
tanımlayıcı olarak desen | (a, b) as tuple1 |
OR deseni | desen1 | desen2 | ([h] | [h; _]) |
AND deseni | desen1 & desen2 | (a, b) & (_, "test") |
Eksiler deseni | identifier :: list-identifier | h :: t |
Liste düzeni | [ pattern_1; ... ; pattern_n ] | [ a; b; c ] |
Dizi düzeni | [| pattern_1; ..; pattern_n |] | [| a; b; c |] |
Ayraçlı desen | ( desen ) | ( a ) |
Tanımlama grubu düzeni | ( pattern_1, ... , pattern_n ) | ( a, b ) |
Kayıt düzeni | { identifier1 = pattern_1; ... ; = identifier_n pattern_n } | { Name = name; } |
Joker karakter deseni | _ | _ |
Tür ek açıklamasıyla birlikte desen oluşturma | pattern : type | a : int |
Tür testi deseni | :? tür [ tanımlayıcı olarak ] | :? System.DateTime as dt |
Null desen | boş | null |
Nameof deseni | nameof expr | nameof str |
Sabit Desenler
Sabit desenler sayısal, karakter ve dize değişmez değerleri, sabit listesi sabitleridir (numaralandırma türü adı dahil edilir). match
Yalnızca sabit desenleri olan bir ifade, diğer dillerdeki bir case deyimiyle karşılaştırılabilir. Giriş değişmez değerle karşılaştırılır ve değerler eşitse desen eşleşir. Değişmez değerin türü girişin türüyle uyumlu olmalıdır.
Aşağıdaki örnek değişmez değer desenlerinin kullanımını gösterir ve ayrıca değişken deseni ve OR deseni kullanır.
[<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
Sabit değer deseninin bir diğer örneği de sabit listesi sabitlerini temel alan bir desendir. Numaralandırma sabitlerini kullanırken numaralandırma türü adını belirtmeniz gerekir.
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
Tanımlayıcı Desenleri
Desen geçerli bir tanımlayıcı oluşturan bir karakter dizesiyse, tanımlayıcının biçimi desenin nasıl eşleşeceğini belirler. Tanımlayıcı tek bir karakterden uzunsa ve büyük harfle başlıyorsa, derleyici tanımlayıcı deseniyle eşleşmeyi dener. Bu desenin tanımlayıcısı Değişmez Değer özniteliği, ayrımcı birleşim olayı, özel durum tanımlayıcısı veya etkin desen olayı ile işaretlenmiş bir değer olabilir. Eşleşen tanımlayıcı bulunmazsa, eşleşme başarısız olur ve bir sonraki desen kuralı olan değişken deseni girişle karşılaştırılır.
Ayrımcı birleşim desenleri basit adlandırılmış durumlar olabilir veya bir değere veya birden çok değer içeren bir tanımlama grubuna sahip olabilirler. Bir değer varsa, değer için bir tanımlayıcı belirtmeniz gerekir. Tanımlama grubu söz konusu olduğunda, tanımlama grubunun her öğesi için tanımlayıcı içeren bir tanımlama grubu deseni veya bir veya daha fazla adlandırılmış birleşim alanı için alan adına sahip bir tanımlayıcı sağlamanız gerekir. Örnekler için bu bölümdeki kod örneklerine bakın.
türüoption
, ve None
olmak üzere iki örneği Some
olan ayrımcı bir birleşimdir. Bir büyük/küçük harf (Some
) bir değere sahiptir, ancak diğeri (None
) yalnızca adlandırılmış bir büyük/küçük harftir. Bu nedenle, Some
büyük/küçük harfle Some
ilişkili değer için bir değişkene sahip olması gerekir, ancak None
tek başına görünmelidir. Aşağıdaki kodda değişkenine var1
büyük/küçük harfle eşleştirilerek Some
elde edilen değer verilir.
let printOption (data : int option) =
match data with
| Some var1 -> printfn "%d" var1
| None -> ()
Aşağıdaki örnekte, ayrımcı birleşim, PersonName
olası ad biçimlerini temsil eden dizelerin ve karakterlerin bir karışımını içerir. Ayrımcı birleşim örnekleri , LastOnly
ve FirstLast
şeklindedirFirstOnly
.
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
Adlandırılmış alanları olan ayrımcı birleşimler için, adlandırılmış bir alanın değerini ayıklamak için eşittir işaretini (=) kullanırsınız. Örneğin, aşağıdaki gibi bir bildirimle ayrımcı bir birleşim düşünün.
type Shape =
| Rectangle of height : float * width : float
| Circle of radius : float
Adlandırılmış alanları bir desen eşleştirme ifadesinde aşağıdaki gibi kullanabilirsiniz.
let matchShape shape =
match shape with
| Rectangle(height = h) -> printfn $"Rectangle with length %f{h}"
| Circle(r) -> printfn $"Circle with radius %f{r}"
Adlandırılmış alanın kullanımı isteğe bağlıdır, bu nedenle önceki örnekte hem hem de Circle(r)
Circle(radius = r)
aynı etkiye sahiptir.
Birden çok alan belirttiğinizde, ayırıcı olarak noktalı virgül (;) kullanın.
match shape with
| Rectangle(height = h; width = w) -> printfn $"Rectangle with height %f{h} and width %f{w}"
| _ -> ()
Etkin desenler, daha karmaşık özel desen eşleştirmesi tanımlamanızı sağlar. Etkin desenler hakkında daha fazla bilgi için bkz . Etkin Desenler.
Tanımlayıcının özel durum olduğu durum, özel durum işleyicileri bağlamında desen eşleştirmede kullanılır. Özel durum işlemede desen eşleştirme hakkında bilgi için bkz. Özel Durumlar: İfadetry...with
.
Değişken Desenleri
Değişken deseni, eşleştirilen değeri bir değişken adıyla atar. Bu ad, simgenin ->
sağındaki yürütme ifadesinde kullanılabilir. Değişken deseni tek başına herhangi bir girişle eşleşir, ancak değişken desenleri genellikle diğer desenler içinde görünür ve bu nedenle tanımlama demetleri ve diziler gibi daha karmaşık yapıların değişkenler halinde ayrıştırılmasını sağlar.
Aşağıdaki örnekte bir tanımlama grubu deseni içindeki değişken deseni gösterilmektedir.
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)
Desen Olarak
Desen as
, sonuna yan tümcesi eklenmiş bir as
desendir. as
yan tümcesi, eşleşen değeri bir ifadenin yürütme ifadesinde kullanılabilecek bir match
ada bağlar veya bu desenin bir let
bağlamada kullanıldığı durumlarda, ad yerel kapsama bağlama olarak eklenir.
Aşağıdaki örnek bir as
desen kullanır.
let (var1, var2) as tuple1 = (1, 2)
printfn "%d %d %A" var1 var2 tuple1
OR Deseni
VEYA deseni, giriş verileri birden çok desenle eşleştiğinde ve sonuç olarak aynı kodu yürütmek istediğinizde kullanılır. OR deseninin her iki tarafının türleri uyumlu olmalıdır.
Aşağıdaki örnekte OR deseni gösterilmektedir.
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)
AND Deseni
AND deseni, girişin iki desenle eşleşmesini gerektirir. VE deseninin her iki tarafının türleri uyumlu olmalıdır.
Aşağıdaki örnek, bu konunun devamında Yer alan Tanımlama Grubu Düzeni bölümünde gösterildiği gibidetectZeroTuple
, ancak burada hem var2
hem de var1
ve değerleri AND deseni kullanılarak elde edilir.
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)
Eksiler Deseni
Eksi deseni, bir listeyi ilk öğeye, başa ve kalan öğeleri (kuyruk) içeren bir listeye ayırmak için kullanılır.
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
Liste Düzeni
Liste düzeni, listelerin bir dizi öğeye ayrıştırılabilmesini sağlar. Liste deseninin kendisi yalnızca belirli sayıda öğe listesiyle eşleşebilir.
// 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 [ ] )
Dizi Deseni
Dizi düzeni liste desenine benzer ve belirli bir uzunluktaki dizileri ayrıştırmak için kullanılabilir.
// 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 [| |] )
Ayraçlı Desen
Parantezler, istenen ilişkilendirmeyi elde etmek için desenler etrafında gruplandırılabilir. Aşağıdaki örnekte, ve deseni ile eksi deseni arasındaki ilişkilendirmeyi denetlemek için parantezler kullanılır.
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
Tanımlama Grubu Deseni
Tanımlama grubu deseni, tanımlama grubu biçimindeki girişlerle eşleşir ve tanımlama grubundaki her konum için desen eşleştirme değişkenleri kullanılarak tanımlama düzeninin bileşen öğelerine ayrıştırılabilmesini sağlar.
Aşağıdaki örnekte tanımlama grubu deseni gösterilmektedir ve değişmez değer desenleri, değişken desenleri ve joker karakter deseni kullanılır.
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)
Kayıt Deseni
Kayıt düzeni, alanların değerlerini ayıklamak için kayıtları ayrıştırmak için kullanılır. Desenin kaydın tüm alanlarına başvurması gerekmez; Atlanan alanlar yalnızca eşleştirmeye katılmaz ve ayıklanmaz.
// 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"
Joker Karakter Deseni
Joker karakter deseni alt çizgi (_
) karakteriyle temsil edilir ve bir değişkene atanmak yerine girişin atılmış olması dışında değişken deseni gibi herhangi bir girişle eşleşir. Joker karakter deseni genellikle diğer desenlerde sembolün sağındaki ->
ifadede gerekli olmayan değerler için yer tutucu olarak kullanılır. Joker karakter deseni, eşleşmeyen herhangi bir girişi eşleştirmek için desen listesinin sonunda da sık sık kullanılır. Joker karakter deseni, bu konudaki birçok kod örneğinde gösterilmiştir. Bir örnek için önceki koda bakın.
Tür Ek Açıklamalarına Sahip Desenler
Desenler tür ek açıklamalarına sahip olabilir. Bunlar diğer tür ek açıklamaları gibi davranır ve diğer tür ek açıklamaları gibi kılavuz çıkarımı. Desenlerdeki tür ek açıklamalarının çevresinde parantezler gereklidir. Aşağıdaki kod, tür ek açıklamasına sahip bir deseni gösterir.
let detect1 x =
match x with
| 1 -> printfn "Found a 1!"
| (var1 : int) -> printfn "%d" var1
detect1 0
detect1 1
Tür Testi Deseni
Tür testi deseni, girişi bir türle eşleştirmek için kullanılır. Giriş türü, desende belirtilen türle (veya türetilmiş türüyle) eşleşiyorsa, eşleşme başarılı olur.
Aşağıdaki örnekte tür testi deseni gösterilmektedir.
open System.Windows.Forms
let RegisterControl(control:Control) =
match control with
| :? Button as button -> button.Text <- "Registered."
| :? CheckBox as checkbox -> checkbox.Text <- "Registered."
| _ -> ()
Tanımlayıcının yalnızca belirli bir türetilmiş türde olup olmadığını kontrol ediyorsanız, aşağıdaki örnekte gösterildiği gibi desenin parçasına ihtiyacınız as identifier
yoktur:
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"
| _ -> ()
Null Desen
Null deseni, null değere izin veren türlerle çalışırken görüntülenebilen null değerle eşleşir. Null desenler sık sık .NET Framework koduyla birlikte çalışırken kullanılır. Örneğin, bir .NET API'sinin dönüş değeri bir match
ifadenin girişi olabilir. Dönüş değerinin null olup olmadığına ve döndürülen değerin diğer özelliklerine göre program akışını denetleyebilirsiniz. Null değerlerin programınızın geri kalanına yayılmasını önlemek için null desenini kullanabilirsiniz.
Aşağıdaki örnek null desenini ve değişken desenini kullanır.
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()
Nameof deseni
Desen, nameof
değeri anahtar sözcüğü izleyen ifadeye eşit olduğunda bir dizeyle eşleşir nameof
. örneğin:
let f (str: string) =
match str with
| nameof str -> "It's 'str'!"
| _ -> "It is not 'str'!"
f "str" // matches
f "asdf" // does not match
Adını nelerin nameof
alabileceğini öğrenmek için işlecine bakın.