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 Noneolmak ü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 , LastOnlyve 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.

Ayrıca bkz.