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}
精彩评论