Desen Eşleştirme
Desenler, giriş verilerini dönüştürmek için kurallardır. Bu değerler, verileri mantıksal bir yapı veya yapılarla karşılaştırmak, verileri yapısal parçalar halinde çıkarmak veya verileri çeşitli yollarla ayıklamak için F # boyunca kullanılır.
Açıklamalar
Desenler, ifadesi gibi birçok dil yapılarında kullanılır match . letBağlamalar, lambda ifadeleri ve ifadeyle ilişkili özel durum işleyicilerde işlevler için bağımsız değişkenleri işlerken kullanılırlar try...with . Daha fazla bilgi için bkz. Match ifadeleri, Let bağlamaları, lambda Ifadeleri: fun anahtar sözcüğüve özel durumlar: try...with ifade.
Örneğin, match ifadesinde, Düzen kanal sembolünü izleyen şeydir.
match expression with
| pattern [ when condition ] -> result-expression
...
Her bir model girişi bir şekilde dönüştürmek için bir kural işlevi görür. matchİfadesinde, her bir model, giriş verilerinin örüntüle uyumlu olup olmadığını görmek için sırasıyla incelenir. Bir eşleşme bulunursa sonuç ifadesi yürütülür. Bir eşleşme bulunmazsa, sonraki model kuralı test edilir. Koşul bölümü eşleşme ifadeleriyleaçıklandığında isteğe bağlı.
Desteklenen desenler aşağıdaki tabloda gösterilmiştir. Çalışma zamanında, giriş, tabloda listelenen sırada aşağıdaki desenlerden her birine karşı test edilir ve desenler yinelemeli olarak, kodunuzda göründükleri gibi ve her satırdaki desenler için soldan sağa uygulanır.
| Ad | Açıklama | Örnek |
|---|---|---|
| Sabit model | Herhangi bir sayısal, karakter veya dize sabiti, bir numaralandırma sabiti veya tanımlanmış değişmez değer tanımlayıcısı | 1.0, "test", 30, Color.Red |
| Tanımlayıcı stili | Ayrılmış birleşimin, özel durum etiketinin veya etkin bir model durumunun Case değeri | Some(x)Failure(msg) |
| Değişken model | Tanımlayıcısını | a |
as kalıp |
tanımlayıcı olarak model | (a, b) as tuple1 |
| VEYA desenli | pattern1 | pattern2 | ([h] | [h; _]) |
| VE model | pattern1 & pattern2 | (a, b) & (_, "test") |
| Dezavantajla | tanımlayıcı :: list-Identifier | h :: t |
| Liste kalıbı | [ pattern_1;...; pattern_n ] | [ a; b; c ] |
| Dizi düzeni | [| pattern_1;..; pattern_n |] | [| a; b; c |] |
| Parantez içine alınmış desenler | ( model ) | ( a ) |
| Tanımlama grubu düzeni | ( pattern_1,..., pattern_n ) | ( a, b ) |
| Kayıt stili | { Identifier1 = pattern_1; ... ; identifier_n = pattern_n } | { Name = name; } |
| Joker karakter stili | _ | _ |
| Tür ek açıklaması ile birlikte desenler | model : tür | a : int |
| Test modelini yazın | :? tür [as Identifier ] | :? System.DateTime as dt |
| Null desenli | null | null |
| NameOf deseninin | ad ifade | nameof str |
Sabit desenler
Sabit desenler sayısal, karakter ve dize değişmez değerleri, numaralandırma sabitleridir (numaralandırma türü adı dahil). matchYalnızca sabit desenleri olan bir ifade, diğer dillerdeki Case ifadesiyle karşılaştırılabilir. Giriş değişmez değerle karşılaştırılır ve Değerler eşitse, model eşleşir. Sabit 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 bir değişken deseni ve ya da 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 başka bir örneği, numaralandırma sabitlerine dayanan bir modeldir. Sabit Listesi sabitleri kullandığınızda 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
Desenler, geçerli bir tanımlayıcı oluşturan karakterlerden oluşan bir dizeyse tanımlayıcı formu, düzenin nasıl eşleştirileceği belirler. Tanımlayıcı tek bir karakterden uzunsa ve büyük harfli bir karakterle başlıyorsa, derleyici tanımlayıcı düzeniyle bir eşleşme yapmayı dener. Bu düzenin tanımlayıcısı, değişmez değer özniteliğiyle, ayırt edici birleşim durumuyla, özel durum tanımlayıcısıyla veya etkin bir model durumuyla işaretlenmiş bir değer olabilir. Eşleşen bir tanımlayıcı bulunamazsa, eşleşme başarısız olur ve sonraki model kuralı, değişken deseninin girişi ile karşılaştırılır.
Ayırt edici bileşim desenleri basit adlandırılmış durumlar olabilir veya bir değer ya da birden çok değer içeren bir tanımlama grubu olabilir. Bir değer varsa, değer için bir tanımlayıcı belirtmeniz gerekir. Bir tanımlama grubu söz konusu olduğunda, bir veya daha fazla adlandırılmış UNION alanı için, kayıt düzeninin her öğesi için tanımlayıcı veya bir alan adı olan bir tanımlayıcı içeren bir tanımlama grubu düzeni sağlamanız gerekir. Örnekler için bu bölümdeki kod örneklerine bakın.
optionTürü, iki durum ve içeren ayrılmış bir birleşimdir Some None . Bir Case ( Some ) bir değere sahiptir, ancak diğeri ( None ) yalnızca adlandırılmış bir durumdur. Bu nedenle, Some servis talebiyle ilişkili değer için bir değişkene sahip olması gerekir Some , ancak None kendisi tarafından görünmelidir. Aşağıdaki kodda değişkenine, var1 servis talebiyle eşleştirerek elde edilen değer verilir Some .
let printOption (data : int option) =
match data with
| Some var1 -> printfn "%d" var1
| None -> ()
Aşağıdaki örnekte, PersonName ayırt edici bileşim, olası ad biçimlerini temsil eden dizelerin ve karakterlerin bir karışımını içerir. Ayırt edici birleşimin durumları, ve ' dir FirstOnly LastOnly 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
Adlandırılmış alanları olan ayrılmış birleşimler için, adlandırılmış bir alanın değerini çıkarmak için eşittir işaretini (=) kullanın. Örneğin, aşağıdaki gibi bir bildirime sahip ayrılmış bir birleşim düşünün.
type Shape =
| Rectangle of height : float * width : float
| Circle of radius : float
Bir model eşleştirme ifadesinde adlandırılmış alanları 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, her ikisi de Circle(r) Circle(radius = r) aynı etkiye sahiptir.
Birden çok alan belirttiğinizde, noktalı virgül kullanın (;) ayırıcı olarak.
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ştirmeyi 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 model eşleştirme içinde kullanılır. Özel durum işlemede model eşleştirme hakkında daha fazla bilgi için bkz. özel durumlar: try...with ifade.
Değişken desenleri
Değişken stili, bir değişken adıyla eşleştirildiği değeri atar ve bu daha sonra simgenin sağ tarafındaki yürütme ifadesinde kullanıma sunulmuştur -> . Bir değişken deseni her türlü girişle eşleşir, ancak değişken desenleri genellikle diğer desenlerde görünür, bu nedenle, değişkenlere ve dizilere gibi daha karmaşık yapıların bağımsız değişkenlere çıkarılması mümkün olur.
Aşağıdaki örnek, bir demet deseninin içindeki değişken bir düzeni gösterir.
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)
as model
asBu model, kendisine eklenmiş bir yan tümcesine sahip bir modeldir as . asYan tümcesi, eşleşen değeri bir ifadenin yürütme ifadesinde kullanılabilecek bir ada bağlar match veya bu düzenin bir bağlamada kullanıldığı durumda let , ad yerel kapsama bir bağlama olarak eklenir.
Aşağıdaki örnek bir model kullanır as .
let (var1, var2) as tuple1 = (1, 2)
printfn "%d %d %A" var1 var2 tuple1
VEYA desenli
OR deseni, giriş verileri birden çok desenle eşleşiyorsa ve sonuç olarak aynı kodu yürütmek istiyorsanız kullanılır. YA da deseninin her iki tarafının türleri uyumlu olmalıdır.
Aşağıdaki örnek, veya modelini gösterir.
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)
VE model
VE 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, detectZeroTuple Bu konunun ilerleyen kısımlarında yer aldığı, ancak her ikisi de ve var1 var2 düzeni kullanılarak değer olarak elde edilen demet düzeni bölümünde gösteriliyor.
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)
Dezavantajla
Cons stili, bir listeyi ilk öğe, baş ve geri kalan öğeleri içeren bir liste, tail ve bir liste için bir liste oluşturmak 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 kalıbı
Liste deseninin, listelerin bir dizi öğe halinde çıkarılması sağlanır. Liste deseninin kendisi yalnızca belirli sayıdaki öğelerin listeleriyle eşleşir.
// 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 düzeni
Dizi düzeni liste düzenine benzer ve belirli uzunluktaki dizileri ayı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 [| |] )
Parantez içine alınmış desenler
Parantezler, istenen ilişkilendirilebilirliği elde etmek için desenlerin etrafında gruplandırılabilir. Aşağıdaki örnekte, parantez ve bir dezavantajla arasındaki ilişkilendirilebilirlik 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 düzeni
Tanımlama grubu düzeni, kayıt düzeni formundaki giriş ile eşleşir ve kayıt düzeninin her bir konum için model eşleme değişkenlerini kullanarak kendi bileşen öğelerine parçalanmak üzere etkin hale gelir.
Aşağıdaki örnek demet desenini gösterir ve aynı zamanda değişmez desenleri, değişken desenleri ve joker karakter desenini kullanı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 stili
Kayıt stili, alanların değerlerini ayıklamak için kayıt oluşturmak için kullanılır. Düzenin kaydın tüm alanlarına başvurması gerekmez; Atlanan tüm 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 stili
Joker karakter stili, alt çizgi ( _ ) karakteriyle temsil edilir ve tıpkı değişken düzeniyle benzer şekilde, girişin bir değişkene atanması yerine atılmasının dışında herhangi bir girişle eşleşir. Joker karakter deseni genellikle diğer desenlerin içinde, simgenin 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 bir desen listesinin sonunda da sık kullanılır. Bu konudaki çok sayıda kod örneğinde joker karakter deseninin gösterildiği gösterilmektedir. Bir örnek için yukarıdaki koda bakın.
Tür ek açıklamalarına sahip desenler
Desenlerin tür ek açıklamaları olabilir. Bunlar diğer tür ek açıklamaları ve diğer tür ek açıklamaları gibi kılavuz çıkarımı gibi davranır. Desenlerdeki tür ek açıklamaları etrafında parantezler gereklidir. Aşağıdaki kod, tür ek açıklamasına sahip bir model gösterir.
let detect1 x =
match x with
| 1 -> printfn "Found a 1!"
| (var1 : int) -> printfn "%d" var1
detect1 0
detect1 1
Test modelini yazın
Tür Test deseninin girişi bir türle eşleştirmek için kullanılır. Giriş türü, düzende belirtilen tür ile bir eşleşmedir (veya türetilmiş bir tür), eşleşme başarılı olur.
Aşağıdaki örnek, tür testi modelini gösterir.
open System.Windows.Forms
let RegisterControl(control:Control) =
match control with
| :? Button as button -> button.Text <- "Registered."
| :? CheckBox as checkbox -> checkbox.Text <- "Registered."
| _ -> ()
Yalnızca bir tanımlayıcının belirli bir türetilmiş türde olup olmadığını denetyorsanız, as identifier Aşağıdaki örnekte gösterildiği gibi, düzenin bir bölümüne ihtiyacınız 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 desenli
Null değer, null değere izin veren türlerle çalışırken görünebilen null değeriyle eşleşir. .NET Framework kodla birlikte çalışırken genellikle Null desenler kullanılır. Örneğin, bir .NET API 'nin dönüş değeri bir ifadenin girdisi olabilir match . Program akışını, dönüş değerinin null ve ayrıca döndürülen değerin diğer özelliklerine göre kontrol edebilirsiniz. Null değerlerin programınızın geri kalanına yayılmasını engellemek için null kalıbı kullanabilirsiniz.
Aşağıdaki örnek, null ve değişken düzenlerini 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 deseninin
nameofDeğeri, anahtar sözcüğünü izleyen ifadeye eşitse, 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
nameofAd alma hakkında bilgi için bkz. işleci.