开发者

Using a Type with collect

I'm trying to dynamically filter (or collect) a list based on type:

If I do this specifying the type explicitly, it works fine

scala> var aList = List("one", 2, 3.3)
aList: List[Any] = List(one, 2, 3.3)

scala> aList.collect{case x:Int => x}
res10: List[Int] = List(2)

If I want to write a method to do this generically, then it doesn't:

scala> def collectType[T](l:List[Any]):List[T] = l.collect{case x:T => x}
warning: there were unchecked warnings; re-run with -unchecked for details
collectType: [T](l: List[Any])List[T]

scala> collectType[Int](aList)
res11: List[Int] = List(one, 2, 3.3)

scala> collectType[Double](aList)  
res16: List[Double] = List(one, 2, 3.3)

scala> collectType[String](aList)
res14: List[String] = List(one, 2, 开发者_高级运维3.3)

I thought at first that it was naming the type 'Integer' rather than using Integer as the type, but that doesn't seem to be the case as:

collectType[Int](aList).foreach(x => println(x))
java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer

It's as though it's deferring checking the type until it's forced to

What am I missing about Types?

Is there a way to achieve what I want to achieve?


After reading through the linked questions, this is what I've come up with. Pretty simple now that it's been pointed out. Taggable is a trait which knows how to hold a map of tags for a class

def matches[F <: Taggable](thing:Taggable)(implicit m:Manifest[F]):Boolean = {
  thing match {
    case e if (m >:> singleType(e)) => true
    case x => false
  }
}
def findByType[G <: Taggable](list:List[Taggable])(implicit m:Manifest[G]) = {
  list.collect{case x if (matches[G](x)) => x}
}


You are missing type erasure. At runtime your method is actually

def collectType(l:List):List = l.collect {case x:Object => x}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜