Предупреждение о аргументе unchecked type в этом совпадении с шаблоном Scala?

Этот файл:

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.

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

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

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

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

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

Ответ 1

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

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: комментарий thoredge для проверки типа. Может быть, мы говорим о разных вещах. Я просто говорил, что:

(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))
}

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

Является ли предупреждение non variable type-argument 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

Ответ 2

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

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)
}