match: основы сопоставления

Сопоставление с образцом — это switch на стероидах: разбор значений по структуре с гарантией полноты.

match — выражение, которое сравнивает значение с набором образцов и возвращает результат первой подошедшей ветки.

От if к match

Цепочки if/elif/else быстро становятся громоздкими. match выражает «в зависимости от формы значения» компактнее и нагляднее.

let describe n =
    match n with
    | 0 -> "ноль"
    | 1 -> "один"
    | _ -> "много"
printfn "%s" (describe 0)
printfn "%s" (describe 5)

Вывод:

ноль
много

Каждая ветка — | образец -> результат. Подчёркивание _ — «любое другое значение» (wildcard), обязательная «ловушка» для остального.

match — это выражение

Важнейшее отличие от switch в C#: match возвращает значение, его результат можно присвоить или вернуть из функции. Все ветки обязаны давать значение одного типа.

let sign x =
    match x with
    | n when n > 0 -> "положительное"
    | 0 -> "ноль"
    | _ -> "отрицательное"
printfn "%s" (sign -3)

Вывод:

отрицательное

Здесь же видно охранное условие when: ветка срабатывает, только если выражение после when истинно.

Исчерпывающность

Компилятор F# проверяет, что образцы покрывают все возможные значения. Если забыть случай, он выдаст предупреждение «Incomplete pattern matches». Это спасает от пропущенных вариантов — особенно ценно для размеченных объединений (об этом дальше).

let onlyTrue b =
    match b with
    | true -> "да"
    // предупреждение: не покрыт случай false

Несколько образцов в ветке

Объединять варианты можно через | внутри ветки.

let isWeekend day =
    match day with
    | "сб" | "вс" -> true
    | _ -> false
printfn "%b" (isWeekend "сб")

Вывод:

true

Как работает под капотом

Компилятор превращает match в дерево решений: эффективную последовательность проверок, а не наивный перебор всех веток подряд. Для размеченных объединений это проверка тега, для констант — таблица переходов. Анализ исчерпывающности — отдельный статический проход: компилятор моделирует пространство значений и ищет непокрытые случаи.

Частые ошибки

  • Забыть ветку _ и получить предупреждение о неполноте — игнорировать его опасно.
  • Делать ветки разного типа результата — все ветки должны возвращать один тип.
  • Ставить when-ветку после общей _ — до неё не дойдёт, важен порядок.

Итоги

  • match сравнивает значение с образцами и возвращает результат подошедшей ветки.
  • Это выражение: результат можно присвоить и вернуть; ветки одного типа.
  • _ — wildcard, when — охранное условие, | — объединение образцов.
  • Компилятор проверяет исчерпывающность образцов.
Проверьте себя
1. Что означает образец _ в match?
AПустую строку
BЛюбое другое значение (wildcard)
CОшибку
DКонец выражения
2. Чем match отличается от switch в C#?
AНичем
Bmatch — это выражение и возвращает значение
Cmatch работает только с числами
Dmatch не проверяет типы
3. Что даёт охранное условие when?
AОстанавливает программу
BСрабатывает ветка только если условие истинно
CОбъявляет переменную
DВключает мутацию