Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Wzorce to reguły przekształcania danych wejściowych. Są one używane w języku F# do porównywania danych ze strukturami logicznymi, rozkładania danych na części składowe lub wyodrębniania informacji z danych na różnorodne sposoby.
Uwagi
Wzorce są używane w wielu konstrukcjach językowych, takich jak wyrażenie match. Są one używane podczas przetwarzania argumentów dla funkcji w powiązaniach let, wyrażeniach lambda i w programach obsługi wyjątków skojarzonych z wyrażeniem try...with. Aby uzyskać więcej informacji, zobacz Match Expressions, let Bindings, Lambda Expressions: The fun Keyword, i Exceptions: The try...with Expression.
Na przykład w wyrażeniu match wzorzec jest zgodny z symbolem potoku.
match expression with
| pattern [ when condition ] -> result-expression
...
Każdy wzorzec działa jako reguła przekształcania danych wejściowych w jakiś sposób. W wyrażeniu match każdy wzorzec jest analizowany z kolei, aby sprawdzić, czy dane wejściowe są zgodne ze wzorcem. Jeśli zostanie znalezione dopasowanie, zostanie wykonane wyrażenie wynikowe. Jeśli dopasowanie nie zostanie znalezione, przetestowana zostanie kolejna reguła wzorca. Opcjonalna część warunku jest objaśniona w sekcji Wyrażenia Dopasowania.
Obsługiwane wzorce przedstawiono w poniższej tabeli. W czasie wykonywania dane wejściowe są testowane względem każdego z poniższych wzorców w kolejności wymienionej w tabeli, a wzorce są stosowane rekursywnie, od pierwszego do ostatniego, gdy pojawiają się w kodzie, a od lewej do prawej dla wzorców w każdym wierszu.
| Nazwa | Opis | Przykład |
|---|---|---|
| Stały wzorzec | Dowolny literał liczbowy, znakowy lub ciągowy, stała wyliczeniowa lub zdefiniowany identyfikator literałowy |
1.0, , "test", , 30Color.Red |
| Wzorzec identyfikatora | Wartość przypadku unii dyskryminowanej, etykiety wyjątku lub aktywnego wzorca przypadku | Some(x)Failure(msg) |
| Zmienny wzorzec | identyfikator | a |
wzorzec as |
wzorzec jako identyfikator | (a, b) as tuple1 |
| WZORZEC OR | wzorzec wzorzec1 | wzorzec2 | ([h] | [h; _]) |
| wzorzec logiczny AND | wzorzec1 & wzorzec2 | (a, b) & (_, "test") |
| Wzorzec wadliwych stron | identyfikator :: identyfikator listy | h :: t |
| Wzorzec listy | [ pattern_1; ... ; pattern_n ] | [ a; b; c ] |
| Schemat tablicy | [| pattern_1; ..; pattern_n |] | [| a; b; c |] |
| Wzorzec ujęty w nawiasy | ( wzorzec ) | ( a ) |
| Wzorzec krotki | ( pattern_1, ... , pattern_n ) | ( a, b ) |
| Wzorzec rekordu | { identyfikator1 = pattern_1; ... ; identifier_n = pattern_n } | { Name = name; } |
| Wzorzec z symbolami wieloznacznymi | _ | _ |
| Wzorzec wraz z adnotacją typu | wzorzec : typ | a : int |
| Wzorzec testu typu | :? wpisz [ jako identyfikator ] | :? System.DateTime as dt |
| Wzorzec o wartości null | null | null |
| Wzorzec nazwy | nazwa wyrażenia | nameof str |
Wzorce stałe
Wzorce stałe to literały liczbowe, znakowe i ciągowe oraz stałe wyliczenia (z uwzględnioną nazwą typu wyliczenia). Wyrażenie match, które ma tylko stałe wzorce, można porównać do instrukcji case w innych językach. Dane wejściowe są porównywane z wartością stałą, a wzorzec jest zgodny, jeśli wartości są równe. Typ literału musi być zgodny z typem danych wejściowych.
W poniższym przykładzie pokazano użycie wzorców literałów, wzorca zmiennej oraz operatora 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
Innym przykładem wzorca literału jest wzorzec oparty na stałych wyliczeniowych. Podczas używania stałych wyliczenia należy określić nazwę typu wyliczenia.
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
Wzorce identyfikatorów
Jeśli wzorzec jest ciągiem znaków, który stanowi prawidłowy identyfikator, formularz identyfikatora określa sposób dopasowania wzorca. Jeśli identyfikator jest dłuższy niż pojedynczy znak i zaczyna się od znaku wielkiej litery, kompilator próbuje dopasować element do wzorca identyfikatora. Identyfikator tego wzorca może być wartością oznaczoną atrybutem Literal, przypadkiem dyskryminowanego związku, identyfikatorem wyjątku lub przypadkiem aktywnego wzorca. Jeśli nie zostanie znaleziony pasujący identyfikator, dopasowanie nie powiedzie się, a następna reguła wzorca, wzorzec zmiennej, zostanie porównana z danymi wejściowymi.
Wzorce unii dyskryminowanej mogą być prostymi przypadkami z nazwą; mogą też mieć wartość albo krotkę zawierającą wiele wartości. Jeśli istnieje wartość, musisz określić identyfikator wartości. W przypadku krotki należy podać wzorzec krotki z identyfikatorem dla każdego elementu krotki lub identyfikatora o nazwie pola dla co najmniej jednego nazwanego pola unii. Zobacz przykłady kodu w tej sekcji, aby zapoznać się z przykładami.
Typ option jest związkiem dyskryminowanym, który ma dwa przypadki, Some i None. Jeden przypadek (Some) ma wartość, ale drugi (None) jest tylko nazwanym przypadkiem. W związku z tym Some musi mieć zmienną dla wartości skojarzonej z przypadkiem Some, ale None musi zostać wyświetlony samodzielnie. W poniższym kodzie zmienna var1 otrzymuje wartość uzyskaną przez dopasowanie do przypadku Some.
let printOption (data : int option) =
match data with
| Some var1 -> printfn "%d" var1
| None -> ()
W poniższym przykładzie związek dyskryminowany PersonName zawiera kombinację ciągów i znaków reprezentujących możliwe formy nazw. Przypadki związków dyskryminowanych są FirstOnly, LastOnlyi 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
W przypadku związków dyskryminowanych, które mają nazwane pola, należy użyć znaku równości (=), aby wyodrębnić wartość nazwanego pola. Rozważmy na przykład dyskryminowaną unię z deklaracją podobną do poniższej.
type Shape =
| Rectangle of height : float * width : float
| Circle of radius : float
Nazwane pola można użyć w wyrażeniu dopasowania wzorca w następujący sposób.
let matchShape shape =
match shape with
| Rectangle(height = h) -> printfn $"Rectangle with length %f{h}"
| Circle(r) -> printfn $"Circle with radius %f{r}"
Użycie nazwanego pola jest opcjonalne, więc w poprzednim przykładzie zarówno Circle(r), jak i Circle(radius = r) mają taki sam efekt.
Podczas określania wielu pól należy użyć średnika (;) jako separatora.
match shape with
| Rectangle(height = h; width = w) -> printfn $"Rectangle with height %f{h} and width %f{w}"
| _ -> ()
Aktywne wzorce umożliwiają definiowanie bardziej złożonego dopasowania niestandardowych wzorców. Aby uzyskać więcej informacji na temat aktywnych wzorców, zobacz Aktywne wzorce.
Przypadek, w którym identyfikator jest wyjątkiem, jest używany w dopasowywaniu wzorców w kontekście procedur obsługi wyjątków. Aby uzyskać informacje o dopasowywaniu wzorców w obsłudze wyjątków, zobacz część Wyjątki: wyrażenie try...with.
Wzorce zmiennych
Wzorzec zmiennej przypisuje dopasowaną wartość do nazwy zmiennej, która jest następnie dostępna do użycia w wyrażeniu wykonawczym po prawej stronie symbolu ->. Sam wzorzec zmiennej jest zgodny z dowolnymi danymi wejściowymi, ale wzorce zmiennych często pojawiają się w innych wzorcach, co umożliwia bardziej złożone struktury, takie jak krotki i tablice, które mają być rozłożone na zmienne.
W poniższym przykładzie pokazano wzorzec zmiennej we wzorcu krotki.
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)
jako wzorzec
Wzorzec as jest wzorcem, który ma dołączony do niego klauzulę as. Klauzula as wiąże dopasowaną wartość z nazwą, która może być używana w wykonawczym wyrażeniu match, lub, w przypadku gdy ten wzorzec jest używany w wiązaniu let, nazwa jest dodawana jako lokalne wiązanie.
W poniższym przykładzie użyto wzorca as.
let (var1, var2) as tuple1 = (1, 2)
printfn "%d %d %A" var1 var2 tuple1
WZORZEC OR
Wzorzec OR jest używany, gdy dane wejściowe mogą być zgodne z wieloma wzorcami i chcesz wykonać ten sam kod w wyniku. Typy obu stron wzorca OR muszą być zgodne.
W poniższym przykładzie pokazano wzorzec 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)
WZORZEC AND
Wzorzec AND wymaga dopasowania danych wejściowych do dwóch wzorców. Typy obu stron wzorca AND muszą być zgodne.
Poniższy przykład jest podobny do detectZeroTuple, pokazany w sekcji dotyczącej wzorca krotki w dalszej części tego tematu, ale w tym przypadku zarówno var1, jak i var2 są uzyskiwane jako wartości przy użyciu wzorca 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)
Wzorzec cons (jeśli w kontekście programowania, zostaw "cons" jako techniczny termin)
Wzorzec cons służy do rozdzielania listy na pierwszy element, head, i listę zawierającą pozostałe elementy, tail.
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
Można również połączyć wiele wzorców konseksji, aby dopasować listy rozpoczynające się od określonych sekwencji elementów.
let charList = ['A'; 'B'; 'C'; 'D']
// This example demonstrates multiple cons patterns.
let matchChars xs =
match xs with
| 'A'::'B'::t -> printfn "starts with 'AB', rest: %A" t
| 'A'::t -> printfn "starts with 'A', rest: %A" t
| 'C'::'D'::t -> printfn "starts with 'CD', rest: %A" t
| _ -> printfn "does not match"
matchChars charList
matchChars ['A'; 'X']
matchChars ['C'; 'D'; 'E']
Wzorzec listy
Wzorzec listy umożliwia rozłożenie list na wiele elementów. Wzorzec listy może być zgodny tylko z listami określonej liczby elementów.
// 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 [ ] )
Wzorzec tablicowy
Wzorzec tablicy przypomina wzorzec listy i może służyć do rozkładania tablic o określonej długości.
// 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 [| |] )
Schemat nawiasów
Nawiasy można grupować wokół wzorców, aby osiągnąć żądaną asocjatywność. W poniższym przykładzie nawiasy służą do kontrolowania asocjacji między wzorcem AND a wzorcem cons.
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
Wzorzec krotki
Wzorzec krotki pasuje do danych wejściowych w formie krotki i umożliwia rozłożenie krotki na elementy składowe przy użyciu zmiennych pasujących do wzorca dla każdej pozycji w krotce.
W poniższym przykładzie pokazano wzorzec krotki, a także używa wzorców literałów, wzorców zmiennych i wzorca symboli wieloznacznych.
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)
Wzorzec rekordu
Wzorzec rekordu służy do dekompilowania rekordów w celu wyodrębnienia wartości pól. Wzorzec nie musi odwoływać się do wszystkich pól rekordu; wszystkie pominięte pola po prostu nie uczestniczą w dopasowywaniu i nie są wyodrębniane.
// 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"
Wzorzec z symbolami wieloznacznymi
Wzorzec z symbolami wieloznacznymi jest reprezentowany przez znak podkreślenia (_) i pasuje do wszystkich danych wejściowych, podobnie jak wzorzec zmiennej, z tą różnicą, że dane wejściowe są odrzucane zamiast przypisywane do zmiennej. Wzorzec symbolu wieloznacznego jest często używany w innych wzorcach jako symbol zastępczy dla wartości, które nie są potrzebne w wyrażeniu po prawej stronie symbolu ->. Wzorzec z symbolami wieloznacznymi jest również często używany na końcu listy wzorców, aby dopasować je do wszelkich niezgodnych danych wejściowych. Wzorzec z symbolami wieloznacznymi przedstawiono w wielu przykładach kodu w tym temacie. Zobacz poprzedni kod, aby zapoznać się z jednym przykładem.
Poniższy kod przedstawia kilka dodatkowych zastosowań wzorca z symbolami wieloznacznymi:
// Wildcard pattern matching "nothing" examples
// Example 1: Wildcard ignoring function parameters
let ignoreAllParams _ _ = "Ignores all input"
// Example 2: Wildcard in destructuring, ignoring elements
let getFirstOnly (first, _) = first
// Example 3: Using wildcard to ignore optional values
let handleEmpty opt =
match opt with
| Some _ -> "Has something"
| None -> "Has nothing"
// Usage
printfn "%s" (ignoreAllParams 42 "test")
printfn "%d" (getFirstOnly (1, "ignored"))
printfn "%s" (handleEmpty None)
Wzorce, które mają adnotacje typu
Wzorce mogą mieć adnotacje typu. Zachowują się one jak inne adnotacje typu i prowadzą wnioskowanie, podobnie jak inne adnotacje typu. Nawiasy są wymagane wokół adnotacji typu we wzorcach.
Wzorzec z adnotacją typu używa składni pattern : type i udostępnia informacje o typie kompilatora czasu do sprawdzania typów. Jest to wyłącznie adnotacja typu statycznego, która pomaga w wnioskowaniu typu — nie wykonuje żadnych kontroli typów ani konwersji typów środowiska uruchomieniowego. Kompilator używa tych informacji podczas kompilacji, aby określić typ zmiennej wzorca.
Poniższy kod przedstawia wzorzec z adnotacją typu:
let detect1 x =
match x with
| 1 -> printfn "Found a 1!"
| (var1 : int) -> printfn "%d" var1
detect1 0
detect1 1
W tym przykładzie (var1 : int) informuje kompilator o var1 typie int. Jest to rozwiązywane w czasie kompilacji, a wygenerowany kod traktuje var1 jako liczbę całkowitą w całym wyrażeniu dopasowania. Ten wzorzec będzie pasować do dowolnej wartości całkowitej i powiązać ją z elementem var1.
Kluczowe cechy:
- Używa składni
pattern : type(z pojedynczym dwukropkiem). - Rozwiązane w czasie kompilacji — dostarcza informacje o typie do narzędzia sprawdzania typów.
- Nie wykonuje testów typu środowiska uruchomieniowego.
- Służy do wnioskowania typów i do kierowania kompilatorem.
Wzorzec testu typu
Wzorzec testu typu służy do dopasowywania danych wejściowych do typu w czasie wykonywania. Jeśli typ danych wejściowych jest dopasowaniem (lub typem pochodnym) typu określonego we wzorcu, dopasowanie powiedzie się.
Wzorzec testu typu używa składni :? type i wykonuje sprawdzanie typu środowiska uruchomieniowego, podobnie jak is operatory lub as w języku C#. Ten wzorzec sprawdza, czy wartość jest określonym typem podczas wykonywania programu, co ułatwia pracę z hierarchiami dziedziczenia lub implementacjami interfejsu.
W poniższym przykładzie pokazano wzorzec testu typu:
open System.Windows.Forms
let RegisterControl(control:Control) =
match control with
| :? Button as button -> button.Text <- "Registered."
| :? CheckBox as checkbox -> checkbox.Text <- "Registered."
| _ -> ()
Jeśli sprawdzasz tylko, czy identyfikator jest określonym typem pochodnym, nie potrzebujesz części wzorca as identifier, jak pokazano w poniższym przykładzie.
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"
| _ -> ()
Kluczowe cechy:
- Używa składni
:? typelub:? type as identifier(z znakiem zapytania). - Rozwiązane w czasie wykonywania — wykonuje sprawdzanie rzeczywistego typu podczas wykonywania.
- Sprawdza, czy wartość jest wystąpieniem określonego typu lub jego typów pochodnych.
- Często używane z hierarchiami dziedziczenia i typami polimorficznymi.
- Podobnie jak operator lub
asoperator języka C#is.
Kontrastujące adnotacje typów i wzorce testów typu
Chociaż oba wzorce obejmują typy, pełnią one bardzo różne cele:
| Funkcja | Wzorzec adnotacji typu (pattern : type) |
Wzorzec testu typu (:? type) |
|---|---|---|
| Syntax | Pojedynczy dwukropek: a : int |
Dwukropek ze znakiem zapytania: :? Button |
| Po rozwiązaniu problemu | Czas kompilacji | Runtime |
| Purpose | Wnioskowanie typu prowadnic | Testuje rzeczywisty typ wartości |
| Przypadek użycia | Pomoc kompilatorowi w zrozumieniu typów | Sprawdzanie typów środowiska uruchomieniowego w hierarchiach dziedziczenia |
| Odpowiednik w języku C# | Adnotacje typu w wzorcach przełączników |
isoperatory lub as |
W poniższym przykładzie przedstawiono różnice:
// Type annotation pattern - compile time
let detect1 x =
match x with
| 1 -> printfn "Found a 1!"
| (var1 : int) -> printfn "%d" var1
// The ': int' tells the compiler var1 is an int
// Everything is resolved at compile time
// Type test pattern - runtime
type A() = class end
type B() = inherit A()
let test (a: A) =
match a with
| :? B -> printfn "Runtime check: it's a B"
| _ -> printfn "Runtime check: it's not a B"
// The ':? B' performs a runtime type check
// The actual type is tested during execution
Wzorzec o wartości null
Wzorzec wartości null jest zgodny z wartością null, która może być wyświetlana podczas pracy z typami, które zezwalają na wartość null. Wzorce o wartości null są często używane podczas współdziałania z kodem programu .NET Framework. Na przykład zwracana wartość interfejsu API platformy .NET może stanowić dane wejściowe wyrażenia match. Przepływ programu można kontrolować na podstawie tego, czy wartość zwracana ma wartość null, a także inne cechy zwracanej wartości. Możesz użyć wzorca null, aby zapobiec propagacji wartości null do pozostałej części programu.
W poniższym przykładzie użyto wzorca null i wzorca zmiennej.
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()
Wzorzec wartości null jest również zalecany w przypadku możliwości wartości null języka F# 9:
let len (str: string | null) =
match str with
| null -> -1
| s -> s.Length
Podobnie można użyć nowych specjalnych wzorców związanych z przechowywaniem wartości null :
let len str = // str is inferred to be `string | null`
match str with
| Null -> -1
| NonNull (s: string) -> s.Length
Wzorzec nazwy
Wzorzec nameof pasuje do ciągu, gdy jego wartość jest równa wyrażeniu, które następuje po słowie kluczowym nameof. Ten wzorzec jest szczególnie przydatny, gdy trzeba dopasować wartości ciągów do nazw typów, przypadków dyskryminowanych unii lub innych symboli w kodzie. Użycie nameof zapewnia bezpieczeństwo w czasie kompilacji, ponieważ jeśli zmienisz nazwę symbolu, wzorzec automatycznie użyje nowej nazwy.
Typowy przypadek użycia polega na deserializacji danych, w których wartości ciągów reprezentują nazwy typów lub przypadków:
type EventType =
| OrderCreated
| OrderShipped
| OrderDelivered
let handleEvent eventName data =
match eventName with
| nameof OrderCreated -> printfn "Processing order creation: %s" data
| nameof OrderShipped -> printfn "Processing order shipment: %s" data
| nameof OrderDelivered -> printfn "Processing order delivery: %s" data
| _ -> printfn "Unknown event type: %s" eventName
handleEvent "OrderCreated" "Order #123" // matches first case
handleEvent "OrderShipped" "Order #123" // matches second case
Takie podejście jest lepsze niż używanie literałów ciągu (na przykład "OrderCreated"), ponieważ:
- Jeśli zmienisz nazwę
OrderCreatednaOrderPlaced, wzorzec zostanie automatycznie zaktualizowany. - Kompilator zapewnia, że symbol istnieje, uniemożliwiając literówki.
- Kod pozostaje spójny podczas refaktoryzacji.
Można również użyć nameof z parametrami:
let f (str: string) =
match str with
| nameof str -> "It's 'str'!"
| _ -> "It is not 'str'!"
f "str" // matches
f "asdf" // does not match
Aby uzyskać informacje, co może mieć nazwę, zobacz operator nameof.