Объяснение сопоставления шаблонов с переключателем

StackOverflow https://stackoverflow.com/questions/199918

Вопрос

Я пытался объяснить разницу между операторами switch и pattern matching (F #) паре людей, но у меня не получилось толком это объяснить .. большую часть времени они просто смотрят на меня и говорят "так почему бы тебе просто не использовать if ..then ..else".

Как бы вы им это объяснили?

РЕДАКТИРОВАТЬ!Спасибо всем за отличные ответы, я действительно хотел бы отметить несколько правильных ответов.

Это было полезно?

Решение

Будучи раньше одним из "таких людей", я не знаю, есть ли краткий способ объяснить, почему сопоставление с образцом - это такое вкусное качество.Это основано на опыте.

Раньше, когда я только взглянул на сопоставление с образцом и подумал, что это прославленный оператор switch, я думаю, что у меня не было опыта программирования с алгебраическими типами данных (кортежи и дискриминируемые объединения) и я не совсем понимал, что сопоставление с образцом является одновременно управляющей конструкцией и связующая конструкция.Теперь, когда я программирую с помощью F #, я, наконец, "понял это".Крутость сопоставления с образцом обусловлена сочетанием функций, найденных в функциональных языках программирования, и поэтому для стороннего наблюдателя это нетривиально, чтобы оценить.

Я попытался подвести итог одному аспекту того, почему сопоставление с шаблоном полезно, во втором из короткой серии блогов из двух частей, посвященных языку и дизайну API;проверьте часть первая и часть вторая.

Другие советы

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

Это позволяет вам писать предельно лаконично.Вы можете проиллюстрировать это небольшим примером, таким как производная функция для простого типа математических выражений:

type expr =
    | Int of int
    | Var of string
    | Add of expr * expr
    | Mul of expr * expr;;

let rec d(f, x) =
    match f with
    | Var y when x=y -> Int 1
    | Int _ | Var _ -> Int 0
    | Add(f, g) -> Add(d(f, x), d(g, x))
    | Mul(f, g) -> Add(Mul(f, d(g, x)), Mul(g, d(f, x)));;

Кроме того, поскольку сопоставление с шаблоном является статической конструкцией для статических типов, компилятор может (i) проверить, что вы рассмотрели все случаи (ii) обнаружить избыточные ветви, которые никогда не могут соответствовать какому-либо значению (iii) обеспечить очень эффективную реализацию (с переходами и т.д.).

Отрывок из эта статья в блоге:

Сопоставление с шаблоном имеет несколько преимуществ по сравнению с операторами switch и отправкой методов:

  • Сопоставления с шаблоном могут воздействовать на целые числа, значения с плавающей точкой, строки и другие типы, а также на объекты.
  • Совпадения с шаблоном могут воздействовать на несколько разных значений одновременно:параллельное сопоставление с образцом.Способ отправка и переключение ограничены одним значением, например"это".
  • Шаблоны могут быть вложенными, что позволяет отправлять по деревьям произвольной глубины.Отправка метода и переключение ограничены для не вложенного случая.
  • Или-шаблоны позволяют использовать подшаблоны общий доступ.Отправка методов разрешает только совместное использование, когда методы принадлежат классам, которые случайно совместно используют базовый класс.В противном случае вы должны вручную разложить общность на отдельную функцию (присвоив ей имя), а затем вручную вставить вызовы из всех подходящих мест в вашу ненужную функцию.
  • Сопоставление с шаблоном обеспечивает избыточность проверка, которая выявляет ошибки.
  • Вложенные и/или параллельной схеме матчи оптимизирована для вас Компилятора F#.Эквивалент OO должен быть написан вручную и постоянно повторно оптимизироваться вручную во время разработки, что является недопустимо утомительным и подверженным ошибкам, поэтому OO-код производственного качества имеет тенденцию быть чрезвычайно медленным по сравнению.
  • Активные шаблоны позволяют вводить пользовательскую семантику отправки.

Навскидку с моей головы:

  1. Компилятор может определить, не рассмотрели ли вы все возможности в своих совпадениях
  2. Вы можете использовать совпадение в качестве задания
  3. Если у вас дискриминируемый союз, каждое совпадение может иметь разный "тип"

Переключатель - это два передних колеса.

Сопоставление с образцом - это весь автомобиль.

Кортежи имеют ",", а варианты имеют аргументы Ctor ..это конструкторы, они создают вещи.

Паттерны - это деструкторы, они разрывают их на части.

Это двойственные понятия.

Чтобы выразить это более убедительно:понятие кортежа или варианта не может быть описано просто его конструктором:деструктор необходим, иначе созданное вами значение бесполезно.Именно эти двойные описания определяют ценность.

Обычно мы рассматриваем конструкторы как данные, а деструкторы - как поток управления.Деструкторы вариантов - это альтернативные ветви (одна из многих), деструкторы кортежей - это параллельные потоки (все из многих).

Параллелизм очевиден в таких операциях , как

(f * g) . (h * k) = (f . h * g . k) 

если вы думаете об управлении, проходящем через функцию, кортежи предоставляют способ разделить вычисление на параллельные потоки управления.

С этой точки зрения выражения - это способы составления кортежей и вариантов для создания сложных структур данных (подумайте об AST).

А совпадения с шаблоном - это способы создания деструкторов (опять же, подумайте об AST).

Совпадения шаблонов в OCaml, помимо того, что они более выразительны, как упоминалось несколькими способами, которые были описаны выше, также дают некоторые очень важные статические гарантии.Компилятор докажет вам, что анализ прецедентов, воплощенный в вашем операторе сопоставления с шаблоном, является:

  • исчерпывающий (ни один случай не пропущен)
  • без избыточности (нет обращений, которые никогда не могут быть обработаны, потому что они вытеснены предыдущим обращением)
  • звук (никаких шаблонов, которые невозможны с учетом рассматриваемого типа данных)

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

Инструкции If-Else (или switch) предназначены для выбора различных способов обработки значения (ввода) в зависимости от свойства о ценности, находящейся под рукой.

Сопоставление с образцом заключается в определении того, как обрабатывать значение с учетом его структура, (также обратите внимание, что совпадения с шаблоном в одном случае имеют смысл).

Таким образом, сопоставление с образцом - это скорее деконструкция значений, чем выбор, это делает их очень удобным механизмом для определения (рекурсивных) функций в индуктивных структурах (рекурсивных типах объединения), что объясняет, почему они так широко используются в таких языках, как Ocaml и т.д.

PS:Возможно, вы знаете "шаблоны" pattern-match и If-Else по их специальному использованию в математике;

"если x обладает свойством A, то y иначе z" (If-Else)

" какой - то термин в p1..pn где ....является простым разложением x .." ((единичный случай) совпадение с шаблоном)

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top