2014-01-25 3 views
9

Все говорят, что сопоставление шаблонов - отличная функция в функциональных языках. Зачем?В чем преимущество использования соответствия шаблону scala вместо java-переключателя?

Не могу я просто использовать ifs и переключатели для всех?

Я хотел бы понять преимущество использования шаблона вместо обычного КСФА процедурного программирования и переключение дел

+5

Может быть лучше для http://programmers.stackexchange.com или даже http://cs.stackexchange.com/help/on-topic. Резюме моего понимания - шаблоны дают вам гораздо большую гибкость, чтобы «сопоставлять и деконструировать» в очень компактной форме. Попробуйте написать случай 'switch' для чего-то вроде« списка из 3-х элементов, где второй имеет особый тип »на обычном языке ... –

+4

Я знаю, что это проблеск, но ... Сравнение шаблонов Scala - это« переключатель »Java как атомная бомба это ручная граната. –

+2

Ручная граната? Я думал больше о лабиринтах ... –

ответ

22

я сначала хотел бы отметить, что вы не используете шаблон сопоставления «вместо» выписок переключателя , В Scala нет операторов switch, то, что у него есть, есть блоки соответствия, причем случаи внутри этого внешне внешне очень похожи на оператор switch.

Соединительные блоки с совпадением рисунков делает все, что switch делает, и многое другое.

A) Он не ограничивается только примитивами и другими типами, которые Oracle выбрал для «благословения» в языке spec (строки и перечисления). Если вы хотите совпадать с вашими собственными типами, идите прямо вперед!

B) Соответствие шаблону также может извлечь. Например, с кортежем:

val tup = ("hello world", 42) 
tup match { 
    case (s,i) => 
    println("the string was " + s) 
    println("the number was " + i 
} 

со списком:

val xs = List(1,2,3,4,5,6) 
xs match { 
    case h :: t => 
    // h is the head: 1 
    // t is the tail: 2,3,4,5,6 
    // The :: above is also an example of matching with an INFIX TYPE 
} 

с корпусом класса

case class Person(name: String, age: Int) 
val p = Person("John Doe", 42) 
p match { 
    case Person(name, 42) => 
    //only extracting the name here, the match would fail if the age wasn't 42 
    println(name) 
} 

С) сопоставление с образцом может быть использовано в присвоении значения и для- соображениями, а не только в контрольных блоках:

val tup = (19,73) 

val (a,b) = tup 

for((a,b) <- Some(tup)) yield a+b // Some(92) 

D), матч блоки представляют собой выражения, а не заявления

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

val result = tup match { case (a,b) => a + b } 
+0

«for ((a, b) <- tup) дает + b» return error: value filter не является членом (Int, Int) –

+0

пример updated –

5

Как-то мой редактировать/дополнение к @KevinWright ответ получил выброшены, поэтому я добавлю его здесь еще один хороший шаблон сопоставления особенность ...

F) проверка Compiler исчерпанность случаев.

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

scala> def badMatch(l: List[Int]): Unit = l match { case x :: xs => println(x) } 
<console>:7: warning: match may not be exhaustive. 
It would fail on the following input: Nil 
     def badMatch(l: List[Int]): Unit = l match { case x :: xs => println(x) } 
             ^
badMatch: (l: List[Int])Unit 

scala> badMatch(List(1, 2)) 
1 

scala> badMatch(Nil) 
scala.MatchError: List() (of class scala.collection.immutable.Nil$) 

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

Если вы используете if вы должны использовать else, и если вы используете Java switch вам придется иметь дело default охватить все случаи. Но обратите внимание на разницу: компилятор Scala знает, что ваш пустой список отличается от непустого списка в этом случае, или в более широком смысле вы определяете детализацию совпадений. Вы можете сопоставлять списки с 1 или 2 элементами и игнорировать остальные или использовать любые другие более сложные шаблоны, не беспокоясь, если вам удастся охватить все случаи.

Вкратце, поскольку вы используете сложное извлечение и сопоставление логического компилятора, убедитесь, что вы не пропустили ни одного случая. На Java нет ничего подобного, если вы не используете случай по умолчанию, например default или else.

+0

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

2

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

+0

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

+0

Это близко, но динамическая отправка может справиться только с одним аргументом, тогда как сопоставление образцов может справиться с несколькими. В языках ООП, если вы хотите рассмотреть два аргумента, вам нужно использовать двойную диспетчеризацию. Http://en.wikipedia.org/wiki/Double_dispatch. Университетские языки программирования 2-го курса Университета Вашингтона имеют хорошее представление о совпадении шаблонов с несколькими аргументами http://bit.ly/1xlGT4U и двойная отправка http://bit.ly/1ETlo0U –

2

Как было написано в других ответах, сопоставление шаблонов Scala и Java-переключатель не делают то же самое.

переключатель заявление:

  • работает только с носителями типов, перечисленных типов, и класс Строка
  • Это является альтернативой цепи «если-то еще», чтобы создать несколько путей выполнения, в соответствии с императивного программирования

сопоставление с образцом:

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

Другими словами, вы можете использовать «сопоставление образцов» для аналогичной цели «java switch», но при этом вы используете функциональные инструменты в императивном порядке.

Смежные вопросы