Когда мы сопоставляем значение с шаблоном, используя Активные шаблоны, неявно вызывается функция «конвертировать». Поэтому вместо того, чтобы писать:
match value with
| Tag1 -> ...
| Tag2 -> ...
Я могу явно написать:
match convert value with
| Tag1 -> ...
| Tag2 -> ...
Таким образом, мне не нужно использовать здесь активные шаблоны. Конечно, я должен явно вызвать функцию convert
и явно объявить тип объединения. Но это мелочи для меня.
Так в чем же суть Active Patterns?
Основная сила сопоставления с образцом заключается не в забавном синтаксисе. Основная сила шаблонов в том, что они могут быть вложенный.
Взгляните на это:
match value with
| Foo (Bar, Baz [First 42; Second "hello!"]) -> "It's a thing"
| Qux [42; 42; 42] -> "Triple fourty-two"
| _ -> "No idea"
Предполагая, что все слова с заглавной буквы являются активными шаблонами, давайте попробуем переписать первый шаблон с точки зрения явного вызова convert
:
match convertFoo value with
| Foo (x, y) ->
match convertBar x, convertBaz y with
| (Bar, Baz [z1; z2]) ->
match convertFirst z1, convertSecond z2 with
| First 42, Second "hello!" -> "It's a thing"
Слишком длинно и запутанно? Но подождите, мы даже не успели написать все несовпадающие ветки!
match convertFoo value with
| Foo (x, y) ->
match convertBar x, convertBaz y with
| (Bar, Baz [z1; z2]) ->
match convertFirst z1, convertSecond z2 with
| First 42, Second "hello!" -> "It's a thing"
| _ -> "No idea"
| _ -> "No idea"
| Qux [42; 42; 42] -> "Triple fourty-two"
| _ -> "No idea"
Видите, как ветвь «Без понятия» троится? Разве копирование и вставка не прекрасны? :-)
Между прочим, именно поэтому слабая попытка C# сделать то, что они имеют наглость назвать «сопоставлением с образцом», на самом деле не является сопоставлением с образцом: оно не может быть вложенным, и поэтому, как вы очень проницательно заметили, это не лучше, чем просто вызов функции классификатора.