此档案:
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 是否是一个3个元素等于1,2和3的Seq。
如果我写了类似的话,我会理解这个警告:
case strings : Seq[String] => ...
为什么我会收到警告,有什么好办法让它消失?
顺便说一句,我确实希望与静态类型的Object匹配。在真正的代码中,我正在解析类似于Lisp数据的东西 - 它可能是一个字符串,基准序列,符号,数字等。
答案 0 :(得分:5)
以下是对场景背后发生的事情的一些见解。请考虑以下代码:
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))
}
使用类型检查,以便在完成强制转换时没有类强制转换异常。
类型模式Seq [A]中的警告非变量类型参数A是否未被选中,因为它被删除被证明是合理的,是否存在可能存在类强制转换异常的情况< em>甚至使用类型检查,我不知道。
编辑:这是一个例子:
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
答案 1 :(得分:4)
至少在外面声明匹配对象会让它消失,但我不确定原因:
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)
}