当使用完全限定的类名参数化时,我在Scala中的对象模式匹配中遇到一些问题。这基于Scala 2.9.0.1。谁知道这段代码有什么问题?
scala> "foo" match {
| case y : Seq[Integer] =>
| case y : Seq[java.lang.Integer] =>
<console>:3: error: ']' expected but '.' found.
case y : Seq[java.lang.Integer] =>
为什么第一个版本有效,但后者失败了?当完全限定的类名用于参数化时,似乎只会出现此问题。
来自 Scala语言规范,8.1节模式,后面的标识符:需要是8.2节中定义的类型模式:
类型模式由类型,类型变量和通配符组成。一种
pattern T是以下形式之一:
...
参数化类型模式T [a(1),. 。 。 ,a(n)],其中a(i)是
类型变量模式或通配符_。这种类型模式匹配所有
对于某种类型的任意实例化,匹配T的值
变量和通配符。这些类型的边界或别名类型
变量如(§8.3)中所述确定。
...
类型变量模式是一个以a开头的简单标识符
小写字母。但是,预定义的基元类型别名
unit,boolean,byte,short,char,int,long,float和double不是
归类为类型变量模式。
因此,从语法上讲,您不能将完全限定的类用作此位置中的类型变量模式。但是,您可以使用类型别名,因此:
type JavaInt = java.lang.Integer
List(new java.lang.Integer(5)) match {
case y: Seq[JavaInt] => 6
case _ => 7
}
将按预期返回6。问题在于Alan Burlison指出,以下内容也会返回6:
List("foobar") match {
case y: Seq[JavaInt] => 6
case _ => 7
}
因为类型正在被删除。您可以通过使用-unchecked选项运行REPL或scalac来查看此信息。
来自 Scala语言规范,8.1节模式,后面的标识符:需要是8.2节中定义的类型模式:
类型模式由类型,类型变量和通配符组成。一种
pattern T是以下形式之一:
...
参数化类型模式T [a(1),. 。 。 ,a(n)],其中a(i)是
类型变量模式或通配符_。这种类型模式匹配所有
对于某种类型的任意实例化,匹配T的值
变量和通配符。这些类型的边界或别名类型
变量如(§8.3)中所述确定。
...
类型变量模式是一个以a开头的简单标识符
小写字母。但是,预定义的基元类型别名
unit,boolean,byte,short,char,int,long,float和double不是
归类为类型变量模式。
因此,从语法上讲,您不能将完全限定的类用作此位置中的类型变量模式。但是,您可以使用类型别名,因此:
type JavaInt = java.lang.Integer
List(new java.lang.Integer(5)) match {
case y: Seq[JavaInt] => 6
case _ => 7
}
将按预期返回6。问题在于Alan Burlison指出,以下内容也会返回6:
List("foobar") match {
case y: Seq[JavaInt] => 6
case _ => 7
}
因为类型正在被删除。您可以通过使用-unchecked选项运行REPL或scalac来查看此信息。
实际上你的第一个例子也不起作用。如果使用-unchecked运行REPL,您将看到以下错误:
警告:非变量类型参数类型模式中的整数Seq [Integer]未被选中,因为它被擦除消除
所以你实际上无法做你想要做的事情 - 在运行时,List [Integer]和List [AnythingElse]之间没有区别,所以你不能对它进行模式匹配。您可以使用Manifest执行此操作,请参阅 http://ofps.oreilly.com/titles/9780596155957/ScalasTypeSystem.html#Manifests 和 http://www.scala-blogs.org/2008/10/manifests-reified-types.html