パターン マッチPattern Matching

パターンは、入力データの変換規則です。Patterns are rules for transforming input data. データを論理構造と比較したり、データを構成要素に分解したり、さまざまな方法でデータから情報を抽出したりするために、F# 言語全体で使用されます。They are used throughout the F# language to compare data with a logical structure or structures, decompose data into constituent parts, or extract information from data in various ways.

RemarksRemarks

パターンは、match 式などの多くの言語構成要素で使用されます。Patterns are used in many language constructs, such as the match expression. let 束縛、ラムダ式、および try...with 式に関連付けられている例外ハンドラーで関数の引数を処理する場合に使用されます。They are used when you are processing arguments for functions in let bindings, lambda expressions, and in the exception handlers associated with the try...with expression. 詳細については、次を参照してください一致式let 束縛ラムダ式:、funキーワード、および例外:、 。try...withします。For more information, see Match Expressions, let Bindings, Lambda Expressions: The fun Keyword, and Exceptions: The try...with Expression.

たとえば、match式、パターンはパイプ記号。For example, in the match expression, the pattern is what follows the pipe symbol.

match expression with
| pattern [ when condition ] -> result-expression
...

各パターンは、なんらかの方法で入力を変換する際の規則として機能します。Each pattern acts as a rule for transforming input in some way. match 式では、各パターンが順に調べられ、入力データにパターンとの互換性があるかどうかが確認されます。In the match expression, each pattern is examined in turn to see if the input data is compatible with the pattern. 一致が見つかった場合は、結果の式が実行されます。If a match is found, the result expression is executed. 一致が見つからなかった場合は、次のパターン規則がテストされます。If a match is not found, the next pattern rule is tested. 省略可能な場合に条件一部については一致式します。The optional when condition part is explained in Match Expressions.

サポートされているパターンを次の表に示します。Supported patterns are shown in the following table. 実行時に、表に示されている順序で次の各パターンに対して入力がテストされます。パターンは、コードに示されているとおりに先頭から末尾へ、各行のパターンの左から右へ、再帰的に適用されます。At run time, the input is tested against each of the following patterns in the order listed in the table, and patterns are applied recursively, from first to last as they appear in your code, and from left to right for the patterns on each line.

名前Name 説明Description Example
定数パターンConstant pattern 数値、文字、リテラル文字列、列挙定数、または定義済みのリテラル識別子Any numeric, character, or string literal, an enumeration constant, or a defined literal identifier 1.0, "test", 30, Color.Red1.0, "test", 30, Color.Red
識別子パターンIdentifier pattern 判別共用体のケース値、例外ラベル、またはアクティブ パターンのケースA case value of a discriminated union, an exception label, or an active pattern case Some(x)

Failure(msg)
変数パターンVariable pattern identifieridentifier a
as パターンas pattern パターンとして識別子pattern as identifier (a, b) as tuple1
OR パターンOR pattern pattern1 | pattern2pattern1 | pattern2 ([h] | [h; _])
AND パターンAND pattern pattern1 & pattern2pattern1 & pattern2 (a, b) & (_, "test")
Cons パターンCons pattern 識別子::一覧識別子identifier :: list-identifier h :: t
リスト パターンList pattern [ pattern_1;... です。pattern_n ][ pattern_1; ... ; pattern_n ] [ a; b; c ]
配列パターンArray pattern [| pattern_1;... です。pattern_n |][| pattern_1; ..; pattern_n |] [| a; b; c |]
かっこで囲まれたパターンParenthesized pattern (パターン)( pattern ) ( a )
タプル パターンTuple pattern ( pattern_1,..., pattern_n )( pattern_1, ... , pattern_n ) ( a, b )
レコード パターンRecord pattern { identifier1 = pattern_1;... です。identifier_n = pattern_n }{ identifier1 = pattern_1; ... ; identifier_n = pattern_n } { Name = name; }
ワイルドカード パターンWildcard pattern _
型の注釈が指定されたパターンPattern together with type annotation パターン:pattern : type a : int
型テスト パターンType test pattern :?:? [として識別子]type [ as identifier ] :? System.DateTime as dt
null パターンNull pattern nullnull null

定数パターンConstant Patterns

定数パターンは、数値、文字、リテラル文字列、列挙定数 (列挙型名が含まれる) です。Constant patterns are numeric, character, and string literals, enumeration constants (with the enumeration type name included). 定数パターンのみが含まれる match 式は、他の言語の case ステートメントと比較できます。A match expression that has only constant patterns can be compared to a case statement in other languages. 入力がリテラル値と比較され、値が等しい場合にはパターンが一致します。The input is compared with the literal value and the pattern matches if the values are equal. リテラルの型に、入力の型との互換性があることが必要です。The type of the literal must be compatible with the type of the input.

リテラル パターンの使用例を次に示します。変数パターンと OR パターンも使用します。The following example demonstrates the use of literal patterns, and also uses a variable pattern and an OR pattern.

[<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

リテラル パターンにはこの他に、列挙定数に基づくパターンもあります。Another example of a literal pattern is a pattern based on enumeration constants. 列挙定数を使用するときは、列挙型名を指定する必要があります。You must specify the enumeration type name when you use enumeration constants.

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

識別子パターンIdentifier Patterns

パターンが有効な識別子になる文字列の場合は、識別子の形式でパターンの照合方法が決まります。If the pattern is a string of characters that forms a valid identifier, the form of the identifier determines how the pattern is matched. 識別子が 2 文字以上で、大文字で始まる場合は、コンパイラが識別子パターンとの照合を試みます。If the identifier is longer than a single character and starts with an uppercase character, the compiler tries to make a match to the identifier pattern. このパターンの識別子は、Literal 属性が指定された値、判別共用体のケース、例外識別子、またはアクティブ パターンのケースです。The identifier for this pattern could be a value marked with the Literal attribute, a discriminated union case, an exception identifier, or an active pattern case. 一致する識別子が見つからない場合は、照合が失敗し、次のパターン規則の変数パターンが入力と比較されます。If no matching identifier is found, the match fails and the next pattern rule, the variable pattern, is compared to the input.

判別共用体パターンは、単純な名前付きケースであるか、値またはタプル (複数の値を含む) を含むかのいずれかです。Discriminated union patterns can be simple named cases or they can have a value, or a tuple containing multiple values. 値が存在する場合は、値の識別子を指定する必要があります。If there is a value, you must specify an identifier for the value. タプルの場合は、タプルの各要素の識別子、または 1 つ以上の名前付きの共用体フィールドのフィールド名の識別子、を持つタプル パターンを指定する必要があります。In the case of a tuple, you must supply a tuple pattern with an identifier for each element of the tuple or an identifier with a field name for one or more named union fields. 例については、このセクションのコード例を参照してください。See the code examples in this section for examples.

option 型は、SomeNone の 2 つのケースを持つ判別共用体です。The option type is a discriminated union that has two cases, Some and None. 一方のケース (Some) には値が含まれますが、もう一方のケース (None) は単なる名前付きケースです。One case (Some) has a value, but the other (None) is just a named case. したがって、Some には、Some ケースに関連付けられた値の変数が必要ですが、None は単体で使用する必要があります。Therefore, Some needs to have a variable for the value associated with the Some case, but None must appear by itself. 次のコードでは、var1 変数に、Some ケースとの照合で取得された値が指定されます。In the following code, the variable var1 is given the value that is obtained by matching to the Some case.

let printOption (data : int option) =
    match data with
    | Some var1  -> printfn "%d" var1
    | None -> ()

次の例では、PersonName 判別共用体に、名前に使用できる形式を表す文字列および文字が混在しています。In the following example, the PersonName discriminated union contains a mixture of strings and characters that represent possible forms of names. 判別共用体のケースは FirstOnlyLastOnly、および FirstLast です。The cases of the discriminated union are FirstOnly, LastOnly, and 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

名前付きフィールドがある判別共用体の場合、名前付きフィールドの値を抽出するために等号 (=) を使用します。For discriminated unions that have named fields, you use the equals sign (=) to extract the value of a named field. たとえば、次のような宣言を持つ判別共用体について検討します。For example, consider a discriminated union with a declaration like the following.

type Shape =
    | Rectangle of height : float * width : float
    | Circle of radius : float

次のようにパターン一致式の中で名前付きフィールドを使用できます。You can use the named fields in a pattern matching expression as follows.

let matchShape shape =
    match shape with
    | Rectangle(height = h) -> printfn "Rectangle with length %f" h
    | Circle(r) -> printfn "Circle with radius %f" r

前の例では、名前付きフィールドの使用は省略可能であり、したがって、Circle(r)Circle(radius = r) は同じ結果になります。The use of the named field is optional, so in the previous example, both Circle(r) and Circle(radius = r) have the same effect.

複数のフィールドを指定する場合は、区切り記号としてセミコロン (;) を使用します。When you specify multiple fields, use the semicolon (;) as a separator.

match shape with
| Rectangle(height = h; width = w) -> printfn "Rectangle with height %f and width %f" h w
| _ -> ()

アクティブ パターンを使用すると、より複雑なカスタム パターン マッチを定義できます。Active patterns enable you to define more complex custom pattern matching. アクティブ パターンの詳細については、次を参照してください。アクティブ パターンします。For more information about active patterns, see Active Patterns.

識別子が例外であるケースは、例外ハンドラーのコンテキストのパターン マッチで使用されます。The case in which the identifier is an exception is used in pattern matching in the context of exception handlers. 例外処理で一致するパターンについては、次を参照してください。例外:、try...withします。For information about pattern matching in exception handling, see Exceptions: The try...with Expression.

変数パターンVariable Patterns

変数パターンでは、照合される値が変数名に割り当てられ、その変数名を、-> 記号の右側の実行式で使用できるようになります。The variable pattern assigns the value being matched to a variable name, which is then available for use in the execution expression to the right of the -> symbol. 変数パターン単体はどの入力にも一致しますが、多くの場合、変数パターンはその他のパターン内で使用されます。このため、タプルや配列などのより複雑な構造体を変数に分解することが可能になります。A variable pattern alone matches any input, but variable patterns often appear within other patterns, therefore enabling more complex structures such as tuples and arrays to be decomposed into variables.

タプル パターン内で変数パターンを使用する例を次に示します。The following example demonstrates a variable pattern within a tuple pattern.

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 パターンas Pattern

as パターンは、as 句が追加されたパターンです。The as pattern is a pattern that has an as clause appended to it. as 句は、照合する値を match 式の実行式で使用できる名前に束縛します。または、このパターンが let 束縛で使用される場合は、名前が束縛としてローカル スコープに追加されます。The as clause binds the matched value to a name that can be used in the execution expression of a match expression, or, in the case where this pattern is used in a let binding, the name is added as a binding to the local scope.

as パターンの使用例を次に示します。The following example uses an as pattern.

let (var1, var2) as tuple1 = (1, 2)
printfn "%d %d %A" var1 var2 tuple1

OR パターンOR Pattern

OR パターンは、入力データが複数のパターンと一致する場合に、同じコードを結果として実行するときに使用します。The OR pattern is used when input data can match multiple patterns, and you want to execute the same code as a result. OR パターンの両側の型に互換性があることが必要です。The types of both sides of the OR pattern must be compatible.

OR パターンの使用例を次に示します。The following example demonstrates the OR pattern.

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 パターンAND Pattern

AND パターンでは、入力が 2 つのパターンと一致する必要があります。The AND pattern requires that the input match two patterns. AND パターンの両側の型に互換性があることが必要です。The types of both sides of the AND pattern must be compatible.

次の例は似ていますdetectZeroTupleに示すように、タプル パターン、このトピックではここで後述する「var1var2AND パターンを使用して、値として取得していますいます。The following example is like detectZeroTuple shown in the Tuple Pattern section later in this topic, but here both var1 and var2 are obtained as values by using the AND pattern.

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)

Cons パターンCons Pattern

Cons パターンは、一覧を最初の要素に分解するために使用、ヘッド、および残りの要素を含む一覧、末尾します。The cons pattern is used to decompose a list into the first element, the head, and a list that contains the remaining elements, the 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

リスト パターンList Pattern

リスト パターンでは、リストをいくつかの要素に分解できます。The list pattern enables lists to be decomposed into a number of elements. リスト パターン自体は、特定の数の要素を含むリストとだけ一致します。The list pattern itself can match only lists of a specific number of elements.

// 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 [ ] )

配列パターンArray Pattern

配列パターンはリスト パターンに似ており、特定の長さの配列を分解するために使用できます。The array pattern resembles the list pattern and can be used to decompose arrays of a specific length.

// 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 "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 [| |] )

かっこで囲まれたパターンParenthesized Pattern

かっこでパターンを囲んで、目的の結合規則を得ることができます。Parentheses can be grouped around patterns to achieve the desired associativity. 次の例では、かっこを使用して、AND パターンと Cons パターンの間の結合規則を制御します。In the following example, parentheses are used to control associativity between an AND pattern and a cons pattern.

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

タプル パターンTuple Pattern

タプル パターンはタプル形式の入力と一致します。このパターンでは、タプル内の位置ごとにパターン マッチ変数を使用して、タプルを構成要素に分解できます。The tuple pattern matches input in tuple form and enables the tuple to be decomposed into its constituent elements by using pattern matching variables for each position in the tuple.

タプル パターンの使用例を次に示します。リテラル パターン、変数パターン、およびワイルドカード パターンも使用します。The following example demonstrates the tuple pattern and also uses literal patterns, variable patterns, and the wildcard pattern.

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)

レコード パターンRecord Pattern

レコード パターンは、レコードを分解してフィールドの値を抽出するために使用されます。The record pattern is used to decompose records to extract the values of fields. パターンがレコードのすべてのフィールドを参照する必要はありません。省略されたフィールドは照合に使用されないため、抽出されません。The pattern does not have to reference all fields of the record; any omitted fields just do not participate in matching and are not extracted.

// 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"

ワイルドカード パターンWildcard Pattern

ワイルドカード パターンは、アンダースコア (_) 文字で表され、変数パターンと同様にどの入力にも一致しますが、入力が変数に割り当てられるのではなく、破棄される点が異なります。The wildcard pattern is represented by the underscore (_) character and matches any input, just like the variable pattern, except that the input is discarded instead of assigned to a variable. 多くの場合、ワイルドカード パターンは、その他のパターン内で -> 記号の右側の式で不要な値のプレースホルダーとして使用されます。The wildcard pattern is often used within other patterns as a placeholder for values that are not needed in the expression to the right of the -> symbol. また、一致しなかった入力に対応するために、パターン リストの最後にワイルドカード パターンが使用されることもよくあります。The wildcard pattern is also frequently used at the end of a list of patterns to match any unmatched input. ワイルドカード パターンは、このトピックの多くのコード例で示されています。The wildcard pattern is demonstrated in many code examples in this topic. 一例として、上記のコードを参照してください。See the preceding code for one example.

型の注釈が付けられたパターンPatterns That Have Type Annotations

パターンには型の注釈を付けることができます。Patterns can have type annotations. このコメントはその他の型の注釈と同様に動作し、その他の型の注釈と同様に推論を導きます。These behave like other type annotations and guide inference like other type annotations. パターンの型の注釈はかっこで囲む必要があります。Parentheses are required around type annotations in patterns. 型の注釈が付けられたパターンを次のコードに示します。The following code shows a pattern that has a type annotation.

let detect1 x =
    match x with
    | 1 -> printfn "Found a 1!"
    | (var1 : int) -> printfn "%d" var1
detect1 0
detect1 1

型テスト パターンType Test Pattern

型テスト パターンは、入力を型と照合するために使用されます。The type test pattern is used to match the input against a type. 入力型がパターンで指定された型と一致する場合、またはその型の派生型である場合は、一致と見なされます。If the input type is a match to (or a derived type of) the type specified in the pattern, the match succeeds.

型テスト パターンの使用例を次に示します。The following example demonstrates the type test pattern.

open System.Windows.Forms

let RegisterControl(control:Control) =
    match control with
    | :? Button as button -> button.Text <- "Registered."
    | :? CheckBox as checkbox -> checkbox.Text <- "Registered."
    | _ -> ()

null パターンNull Pattern

null パターンは null 値と一致します。null 値は、null 値を許可する型を使用しているときに示される可能性があります。The null pattern matches the null value that can appear when you are working with types that allow a null value. Null パターンは、.NET Framework コードで相互運用するときによく使用されます。Null patterns are frequently used when interoperating with .NET Framework code. たとえば、.NET API の戻り値が match 式への入力である場合が考えられます。For example, the return value of a .NET API might be the input to a match expression. プログラム フローは、戻り値が null であるかどうかと、戻り値のその他の特性に基づいて制御できます。You can control program flow based on whether the return value is null, and also on other characteristics of the returned value. null パターンを使用すると、null 値が残りのプログラムに反映されるのを防ぐことができます。You can use the null pattern to prevent null values from propagating to the rest of your program.

null パターンと変数パターンの使用例を次に示します。The following example uses the null pattern and the variable pattern.

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()

関連項目See also