Scala收集类型模式和类型擦除

时间:2014-04-08 04:37:07

标签: scala types erasure

val a = List ("a", 1, 2.34, "b", List(6,7))
a: List[Any] = List(a, 1, 2.34, b, List(6, 7))

等等

a.collect { case s: String => s }
res: List[String] = List(a, b)

然而

a.collect { case s: List[Int] => s }

警告

non-variable type argument Int in type pattern List[Int] is unchecked 
since it is eliminated by erasure
              a.collect { case s: List[Int] => s }
                                  ^
res: List[List[Int]] = List(List(6, 7))

因此要问是否有一种无警告/正确的方法来收集整数列表。

非常感谢。

2 个答案:

答案 0 :(得分:3)

在JVM上,运行时没有足够的信息来知道List是否是List [Int]。即使List [Any]可能恰好只包含Ints,也绝对没有办法告诉它有哪种编译时类型。但是,您可以编写以下几种方法之一:

  1. 对于a中的每个List,产生Ints的子集。

  2. 将列表生成为仅包含Ints的列表。

  3. 与#1相同,但删除空列表。

  4. 例如,#1可以编码为

    a collect { case list:List[_] => list collect { case x:Int => x } }
    

答案 1 :(得分:1)

作为@ AmigoNico答案的补充,有一些实用程序函数将所有这些封装在一个干净的,类型安全的函数后面,例如ShapelessTypeable类型类。

使用无形2.0.0-M1:

scala> val a = List ("a", 1, 2.34, "b", List(6,7))
a: List[Any] = List(a, 1, 2.34, b, List(6, 7))

scala> import syntax.typeable._
import syntax.typeable._

scala> a.flatMap(_.cast[List[Int]])
res0: List[List[Int]] = List(List(6, 7))

scala> a.flatMap(_.cast[List[String]])
res1: List[List[String]] = List()

在无形状功能概述中查看Type safe cast