关于此Scala模式匹配中未经检查的类型参数的警告?

Rob*_*b N 13 scala pattern-matching type-parameter

这个文件:

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)
}
Run Code Online (Sandbox Code Playgroud)

给出这个警告:

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"
Run Code Online (Sandbox Code Playgroud)

Scala版本2.9.0.1.

我没有看到如何执行匹配需要擦除类型参数.第一个案例子句是为了询问obj是否是一个3个元素等于1,2和3的Seq.

如果我写了类似的东西,我会理解这个警告:

case strings : Seq[String] => ...
Run Code Online (Sandbox Code Playgroud)

为什么我会收到警告,什么是让它消失的好方法?

顺便说一句,我确实希望与静态类型的Object匹配.在实际代码中,我正在解析类似于Lisp基准的东西 - 它可能是一个字符串,基准序列,符号,数字等.

huy*_*hjl 5

以下是对场景背后发生的事情的一些见解.考虑以下代码:

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

如果你编译scalac -Xprint:12 -unchecked,你会在擦除阶段(id 13)之前看到代码.对于第一种类型的模式,您将看到如下内容:

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

对于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);
  // ...
}
Run Code Online (Sandbox Code Playgroud)

在这两种情况下,都有一个类型测试来查看对象是否是类型Seq(Seq[Int]Seq[A]).在擦除阶段将消除类型参数.因此警告.即使第二个可能是意外的,检查类型也是有意义的,因为如果对象不是类型Seq,则该子句将不匹配,并且JVM可以继续执行下一个子句.如果类型不匹配,那么该对象可以被强制转换为SequnapplySeq可以被调用.


RE:thoredge评论类型检查.可能我们正在谈论不同的事情.我只是说:

(o: Object) match {
  case Seq(i) => println("seq " + i)
  case Array(i) => println("array " + i)
}
Run Code Online (Sandbox Code Playgroud)

转换为:

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))
}
Run Code Online (Sandbox Code Playgroud)

使用类型检查,以便在完成转换时没有类转换异常.

类型模式Seq [A]中的警告非变量类型参数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
Run Code Online (Sandbox Code Playgroud)