Поделиться через


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

Выражение 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
| ...

Замечания

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

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

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

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

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

В следующем коде показаны некоторые способы 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

См. также