Pattern matching (сопоставление шаблонов/паттернов) представляет механизм, который позволяет сопоставить некоторое выражение с определенным шаблоном. И если сопоставление прошло успешно, то выполняются определенные действия. Для сопоставления шаблонов язык F# предоставляет конструкцию match:
match выражение with | шаблон_1 -> выполняемые_действия_1 | шаблон_2 -> выполняемые_действия_2 | шаблон_N -> выполняемые_действия_N
После оператора match указывается сравниваемое выражение. Затем после оператора with определяются шаблоны, с которым сравнивается выражение. Перед каждым шаблон ставится вертикальная черта |:
| шаблон_1 -> выполняемые_действия_1
После шаблона через оператор -> указываются действия, которые выполняются, если выражение соответствует данному шаблону.
В итоге конструкция match просматривает по порядку шаблоны и сравнивает с ними выражение. Если найден шаблон, которому соответствует выражение, то выполняются указанные для шаблона действия. И дальше шаблоны не проверяются.
Если ни один из шаблонов не соответствует выражению, то никакие действия не выполняются.
Существует много типов сопоставления шаблонов. И для начала возьмем самый простой - сопоставление с константами или constant pattern
Constant pattern предполагает, что выражение сравнивается с константными значениями, например, литералами - числами, строками, символами, а также со значениями перечислений:
let number = 2 match number with | 1 -> printfn "Number is one" | 2 -> printfn "Number is two" | 3 -> printfn "Number is three" printfn "End of Program" // инструкция после конструкции match
Здесь значение number сравнивается с рядом констант - числами 1, 2, 3. Поскольку это значение равно 2, то будет выполняться действие printfn "Number is two"
. И в данном случае мы получим следующий консольный вывод:
Number is two End of Program
Не всегда имеющиеся шаблоны могут покрыть все возможные варианты значений. Например, переменная number может иметь значение, которое не соответствует ни одному из шаблонов. И если шаблон не будет найден, то мы получим ошибку во время выполнения программы. В этом случае мы можем применять универсальный шаблон _, который будет соответствовать все другим вариантам:
let number = 2 match number with | 1 -> printfn "Number is one" | 2 -> printfn "Number is two" | 3 -> printfn "Number is three" | _ -> printfn "Undefined number" printfn "End of Program" // инструкция после конструкции match
Теперь переменная number не соответствует ни одному из константых шаблонов, поэтому она будет соответствовать универсальному шаблону _. И мы получим следующий консольный вывод:
Undefined number End of Program
Подобным образом можно сопсотавлять с константами, определенными в перечислениях:
// перечисление color с тремя константами type Color = | Red = 0 | Green = 1 | Blue = 2 let color = Color.Red match color with | Color.Red -> printfn "Red" | Color.Green -> printfn "Green" | Color.Blue -> printfn "Blue" | _ -> ()
Конструкция match может возвращать значение, которое можно присвоить или возвратить из функции:
let number = 1 let result = match number with | 1 -> "Number is one" | 2 -> "Number is two" | 3 -> "Number is three" | _ -> "Undefined number" printfn "%s" result // Number is one
Здесь в зависимости от результата конструкция match возвращает определенную строку, которая присваивается значению result. Обратите внимание, что шаблоны должны иметь то же количество отступов от начала строки, что и оператор match
Сопоставление идентификаторов или identifier pattern позволяет сопоставить выражение с идентификатором и обычно применяется для сопоставления с вариантами дискриминированных объединений. Например:
// дискриминированное объединение type FamilyStatus = | Married | Single | Complicated let status: FamilyStatus = Married match status with | Married -> printfn "женат/замужем" | Single -> printfn "холост/не замужем" | Complicated -> printfn "все сложно"
Здесь определено объединение FamilyStatus, которое представляет семейный статус и которое определяет три варианта. Конструкция match принимает значение этого типа - значение status и последовательно сравнивает его с возможными случаями объединения. И в зависимости от результата выводит ту или иную строку на консоль.