【问题标题】:Scala collect type pattern and type erasureScala 收集类型模式和类型擦除
【发布时间】:2014-04-08 19:24:17
【问题描述】:

让

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

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

非常感谢。

【问题讨论】:

    标签: scala types erasure


    【解决方案1】:

    在 JVM 上,在运行时没有足够的信息来判断 List 是否是 List[Int]。即使是 List[Any] 也可能恰好只包含 Ints,并且绝对无法判断它具有哪种编译时类型。但是,您可以编写以下代码之一:

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

    2. 在 a 中生成仅包含 Ints 的列表。

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

    例如,#1 可以编码为

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

    【讨论】:

    • 非常感谢这个澄清的答案。
    【解决方案2】:

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

    使用无形 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。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-30
      • 2012-05-28
      • 1970-01-01
      • 1970-01-01
      • 2020-07-27
      • 2012-08-12
      相关资源
      最近更新 更多