Объяснение сопоставления с моделью - PullRequest
55 голосов
/ 14 октября 2008

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

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

EDIT! Спасибо всем за отличные ответы, я действительно хотел бы отметить несколько правильных ответов.

Ответы [ 9 ]

37 голосов
/ 14 октября 2008

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

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

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

30 голосов
/ 14 октября 2008

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

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

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) обеспечить очень эффективную реализацию прыжки и т. д.).

15 голосов
/ 19 октября 2008

Выдержка из этой статьи блога :

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

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

с макушки головы:

  1. Компилятор может сказать, не охватили ли вы все возможности в ваших матчах
  2. Вы можете использовать совпадение в качестве назначения
  3. Если у вас есть дискриминационный союз, у каждого совпадения может быть свой «тип»
5 голосов
/ 05 января 2011

У кортежей есть ",", а у вариантов - аргументы Ctor. Это конструкторы, они создают вещи.

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

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

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

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

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

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

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

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

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

5 голосов
/ 15 октября 2008

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

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

3 голосов
/ 08 февраля 2009

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

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

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

0 голосов
/ 11 апреля 2017

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

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

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

PS: Вы могли бы знать «образцы» и «шаблоны» If-Else по их специальному использованию в математике;

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

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

0 голосов
/ 14 октября 2008

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

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

...