Подтвердить что ты не робот

Scala: проблема совпадения шаблонов с полностью квалифицированными именами классов при параметризации

У меня есть небольшая проблема в шаблоне, сопоставляющем объект в Scala, когда он параметризуется с полным именем класса. Это основано на Scala 2.9.0.1. Кто-нибудь знает, что не так с этим кодом?

scala> "foo" match {
 | case y : Seq[Integer] =>
 | case y : Seq[java.lang.Integer] =>
<console>:3: error: ']' expected but '.' found.
   case y : Seq[java.lang.Integer] =>

Почему первая версия работает, но последняя не работает? Проблема только возникает, когда для параметризации используется полное имя класса.

4b9b3361

Ответ 1

Из Scala Спецификация языка, раздел 8.1 Шаблоны, идентификатор после: должен быть тем, что называется шаблоном типа, определенным в разделе 8.2

Типовые шаблоны состоят из типов, переменных типа и подстановочных знаков. Тип шаблон T имеет одну из следующих форм:

...

Параметрированный шаблон типа T [a (1),.,, a (n)], где a (i) являются тип переменных шаблонов или подстановочных знаков _. Этот тип шаблона соответствует всем значения, соответствующие T для некоторого произвольного экземпляра типа переменные и подстановочные знаки. Оценки или псевдоним типа переменная определяется, как описано в (§8.3).

...

Шаблон переменной типа - это простой идентификатор, который начинается с строчная буква. Однако предопределенные примитивные псевдонимы типов unit, boolean, byte, short, char, int, long, float и double не являются классифицируются как шаблоны переменных типа.

Итак, синтаксически, вы не можете использовать полностью квалифицированный класс как шаблон переменной типа В ЭТОМ ПОЛОЖЕНИИ. Однако вы можете использовать псевдоним типа, поэтому:

type JavaInt = java.lang.Integer
List(new java.lang.Integer(5)) match {
    case y: Seq[JavaInt] => 6
    case _ => 7
}

вернет 6, как ожидалось. Проблема состоит в том, что, как указывает Алан Бурлисон, следующее также возвращает 6:

List("foobar") match {
    case y: Seq[JavaInt] => 6
    case _ => 7
}

потому что тип стирается. Вы можете увидеть это, запустив REPL или scalac с помощью опции -unchecked.

Ответ 2

На самом деле ваш первый пример тоже не работает. Если вы запустите REPL с -unchecked, вы увидите следующую ошибку:

warning: non variable type-argument Целое число в шаблоне типа Seq [Integer] не отмечено, поскольку оно устраняется стиранием

Таким образом, вы не можете на самом деле делать то, что вы пытаетесь сделать - во время выполнения нет никакой разницы между List [Integer] и List [AnythingElse], поэтому вы не можете сопоставить шаблон с ним. Вы можете сделать это с помощью манифеста, см. http://ofps.oreilly.com/titles/9780596155957/ScalasTypeSystem.html#Manifests и http://www.scala-blogs.org/2008/10/manifests-reified-types.html