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

关于此Scala模式匹配中未选中类型参数的警告?,scala,pattern-matching,type-parameter,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) } 给出以下警告: Test.scala:6: warning: non variable type-argument A in type

此文件:

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] => ...
<synthetic> val temp1: java.lang.Object = new java.lang.Object();
if (temp1.isInstanceOf[Seq[Int]]()) 
<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);
  // ...
}
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))
}
为什么我会得到警告,什么是让它消失的好方法


顺便说一句,我确实想与静态类型的对象进行匹配。在实际代码中,我正在解析类似于Lisp数据的东西—它可能是字符串、数据序列、符号、数字等。

下面是一些关于场景背后发生的事情的见解。考虑这个代码:

class Test {
  new Object match { case x: Seq[Int] => true }
  new Object match { case Seq(1) => true }
}
如果使用
scalac-Xprint:12-unchecked进行编译,您将在擦除阶段(id 13)之前看到代码。对于第一种类型模式,您将看到如下内容:

case strings : Seq[String] => ...
<synthetic> val temp1: java.lang.Object = new java.lang.Object();
if (temp1.isInstanceOf[Seq[Int]]()) 
<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);
  // ...
}
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))
}
在这两种情况下,都有一个类型测试,以查看对象是否属于
Seq
Seq[Int]
Seq[a]
)类型。类型参数将在擦除阶段消除。这就是警告。即使第二个可能是意外的,检查类型也是有意义的,因为如果对象不是
Seq
类型,则该子句将不匹配,JVM可以继续执行下一个子句。如果类型匹配,则可以将对象强制转换为
Seq
,并且可以调用
unplyseq


回复:thoredge对类型检查的评论。也许我们在谈论不同的事情。我只是说:

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

case strings : Seq[String] => ...
<synthetic> val temp1: java.lang.Object = new java.lang.Object();
if (temp1.isInstanceOf[Seq[Int]]()) 
<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);
  // ...
}
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))
}
使用类型检查,以便在完成转换时不会出现类转换异常

类型模式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

在外部声明match对象至少会使它消失,但我不确定原因:

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

有趣的是,Scala版本2.8.1在本例中没有给出此警告case@thoredge,我猜2.9.0中的警告可能被认为是一种改进。我不知道这件事是不是已经预见到了。那么它是一个bug吗?在这种情况下,类型检查只是一种优化。@thoredge,如果没有类型检查,当对象不是
Seq
类型时,与试图匹配后续子句相比,您会得到ClassCaseException。如果我将对象更改为Map(1->2,2->3),Map(“1”->“2”,“2”->“3”);或者对于带有-Xprint的matterWith,我得到
案例集合。this.Seq.unallyseq[A]()(Array[A]{1,2,3})=>
。。。我不知道那是什么,但没有检查实例。@thoredge,你不会得到ClassCastException,因为编译器添加了检查实例。是的,找到了。这是因为在本例中,它使用了一个稳定的标识符模式,并且这些模式只编译为一个相等测试(根据语言规范),不需要强制转换。如果你想绑定变量,那就太倒霉了。很高兴知道,但我需要绑定变量。如果我匹配一个类型(比如
Seq[Int]
),任何整数序列都被认为是有效的匹配(不仅仅是(12,3))?