Выражения сопоставления

Выражение match предоставляет элемент управления ветвлением, основанный на сравнении выражения с набором шаблонов.

Синтаксис

// Match expression.
match test-expression with
| pattern1 [ when condition ] -> result-expression1
| pattern2 [ when condition ] -> result-expression2
| ...

// Pattern matching function.
function
| pattern1 [ when condition ] -> result-expression1
| pattern2 [ when condition ] -> result-expression2
| ...

Remarks

Выражения сопоставления шаблонов позволяют выполнять сложные ветвления на основе сравнения тестового выражения с набором шаблонов. match В выражении выражение теста сравнивается с каждым шаблоном, и при обнаружении совпадения вычисляется соответствующее результирующее выражение, а результирующее значение возвращается в качестве значения выражения соответствия.

Функция сопоставления шаблонов, показанная в предыдущем синтаксисе, является лямбда-выражением, в котором сопоставление шаблонов выполняется немедленно в аргументе. Функция сопоставления шаблонов, показанная в предыдущем синтаксисе, эквивалентна следующему.

fun arg ->
    match arg with
    | pattern1 [ when condition ] -> result-expression1
    | pattern2 [ when condition ] -> result-expression2
    | ...

Дополнительные сведения о лямбда-выражениях см. в лямбда-выражениях: ключевое fun слово.

Весь набор шаблонов должен охватывать все возможные совпадения входной переменной. Часто шаблон подстановочных знаков (_) используется в качестве последнего шаблона для сопоставления любых ранее несовпаденных входных значений.

В следующем коде показаны некоторые способы match использования выражения. Справочные материалы и примеры всех возможных шаблонов, которые можно использовать, см. в разделе "Сопоставление шаблонов".

let list1 = [ 1; 5; 100; 450; 788 ]

// Pattern matching by using the cons pattern and a list
// pattern that tests for an empty list.
let rec printList listx =
    match listx with
    | head :: tail -> printf "%d " head; printList tail
    | [] -> printfn ""

printList list1

// Pattern matching with multiple alternatives on the same line.
let filter123 x =
    match x with
    | 1 | 2 | 3 -> printfn "Found 1, 2, or 3!"
    | a -> printfn "%d" a

// The same function written with the pattern matching
// function syntax.
let filterNumbers =
    function | 1 | 2 | 3 -> printfn "Found 1, 2, or 3!"
             | a -> printfn "%d" a

Охранники по шаблонам

Можно использовать when предложение, чтобы указать дополнительное условие, которое переменная должна соответствовать шаблону. Такое предложение называется охранником. Выражение, следующее за ключевым словом when , не вычисляется, если только совпадение не выполняется с шаблоном, связанным с этим охранником.

В следующем примере показано использование охранника для указания числового диапазона для шаблона переменной. Обратите внимание, что несколько условий объединяются с помощью логических операторов.

let rangeTest testValue mid size =
    match testValue with
    | var1 when var1 >= mid - size/2 && var1 <= mid + size/2 -> printfn "The test value is in range."
    | _ -> printfn "The test value is out of range."

rangeTest 10 20 5
rangeTest 10 20 10
rangeTest 10 20 40

Обратите внимание, что поскольку значения, отличные от литерала, не могут использоваться в шаблоне, необходимо использовать when предложение, если необходимо сравнить часть входных данных со значением. Это продемонстрировано в приведенном ниже коде.

// This example uses patterns that have when guards.
let detectValue point target =
    match point with
    | (a, b) when a = target && b = target -> printfn "Both values match target %d." target
    | (a, b) when a = target -> printfn "First value matched target in (%d, %d)" target b
    | (a, b) when b = target -> printfn "Second value matched target in (%d, %d)" a target
    | _ -> printfn "Neither value matches target."
detectValue (0, 0) 0
detectValue (1, 0) 0
detectValue (0, 10) 0
detectValue (10, 15) 0

Обратите внимание, что когда шаблон объединения охватывается охранником, охранник применяется ко всем шаблонам, а не только к последнему. Например, учитывая следующий код, охранник when a > 41 применяется к обоим A a и B a:

type Union =
    | A of int
    | B of int

let foo() =
    let test = A 42
    match test with
    | A a
    | B a when a > 41 -> a // the guard applies to both patterns
    | _ -> 1

foo() // returns 42

См. также