Предупреждение о непроверенном аргументе типа в этом сопоставлении с шаблоном Scala? - PullRequest
13 голосов
/ 02 сентября 2011

Этот файл:

object Test extends App {
    val obj = List(1,2,3) : Object
    val res = obj match {
       case Seq(1,2,3) => "first"
       case _ => "other"
    }
    println(res)
}

выдает это предупреждение:

Test.scala:6: warning: non variable type-argument A in type pattern Seq[A]  
is unchecked since it is eliminated by erasure
   case Seq(1,2,3) => "first"

Scala версия 2.9.0.1.

Я не вижу, как стертый параметр типа необходим для выполнения сопоставления. Это первое предложение case предназначено для запроса, является ли obj Seq с 3 элементами, равными 1, 2 и 3.

Я бы понял это предупреждение, если бы написал что-то вроде:

case strings : Seq[String] => ...

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

Кстати, я хочу сопоставить что-то со статическим типом Object. В реальном коде я анализирую что-то вроде данных о Лиспе - это может быть строка, последовательность данных, символ, число и т. Д.

Ответы [ 2 ]

5 голосов
/ 02 сентября 2011

Вот немного понимания того, что происходит за сценой. Рассмотрим этот код:

class Test {
  new Object match { case x: Seq[Int] => true }
  new Object match { case Seq(1) => true }
}

Если вы скомпилируете с scalac -Xprint:12 -unchecked, вы увидите код непосредственно перед фазой стирания (id 13). Для первого шаблона типа вы увидите что-то вроде:

<synthetic> val temp1: java.lang.Object = new java.lang.Object();
if (temp1.isInstanceOf[Seq[Int]]()) 

Для шаблона извлечения Seq вы увидите что-то вроде:

<synthetic> val temp3: java.lang.Object = new java.lang.Object();
if (temp3.isInstanceOf[Seq[A]]()) {
  <synthetic> val temp4: Seq[A] = temp3.asInstanceOf[Seq[A]]();
  <synthetic> val temp5: Some[Seq[A]] = collection.this.Seq.unapplySeq[A](temp4);
  // ...
}

В обоих случаях существует проверка типа, чтобы определить, относится ли объект к типу Seq (Seq[Int] и Seq[A]). Типовые параметры будут исключены на этапе стирания. Таким образом, предупреждение. Даже если второе может быть неожиданным, имеет смысл проверить тип, поскольку, если объект не относится к типу Seq, это предложение не будет совпадать, и JVM может перейти к следующему предложению. Если тип совпадает, то объект может быть приведен к Seq и unapplySeq.


RE: комментарий к проверке типа. Может быть, мы говорим о разных вещах. Я просто говорил, что:

(o: Object) match {
  case Seq(i) => println("seq " + i)
  case Array(i) => println("array " + i)
}

переводится в нечто вроде:

if (o.isInstanceOf[Seq[_]]) { // type check
  val temp1 = o.asInstanceOf[Seq[_]] // cast
  // verify that temp1 is of length 1 and println("seq " + temp1(0))
} else if (o.isInstanceOf[Array[_]]) { // type check
  val temp1 = o.asInstanceOf[Array[_]] // cast
  // verify that temp1 is of length 1 and println("array " + temp1(0))
}

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

Является ли предупреждение не переменным аргументом типа A в шаблоне типа Seq [A] неконтролируемым, поскольку оно устраняется стиранием , является ли оправданным, и будут ли случаи, когда может быть исключение приведения класса даже с проверкой типа, я не знаю.

Редактировать: вот пример:

object SeqSumIs10 {
  def unapply(seq: Seq[Int]) = if (seq.sum == 10) Some(seq) else None
}

(Seq("a"): Object) match {
  case SeqSumIs10(seq) => println("seq.sum is 10 " + seq) 
}
// ClassCastException: java.lang.String cannot be cast to java.lang.Integer
4 голосов
/ 02 сентября 2011

Объявление объекта совпадения по крайней мере заставляет его исчезнуть, но я не уверен, почему:

class App
  object Test extends App {
  val obj = List(1,2,3) : Object
  val MatchMe = Seq(1,2,3)
  val res = obj match {
    case MatchMe => "first"
    case _ => "other"
  }
  println(res)
}
...