I have read TypeTag related article, but I am unable to realize filter a collection by elements type.
Example:
trait A
class B extends A
class C extends A
val v = Vector(new B,new C)
v filter ( _.isInstanceOf[B] )
The code above works fine.
However I want to extract filter out of v. E.g.
def filter[T,T2](data:Traversable[T2]) = (data filter ( _.isInstanceOf[T])).asInstanceOf[Traversable[T]]
//Then filter v by
filter[B,A](v)
In this case I get warning abstract type T is unchecked since it is eliminated by erasure. I tried to use TypeTag, but it seems not easy to get Type on runtime.
Is there any elegant solution to realize function filter?
Any solution via scala macro is also acceptable.
You need to provide a
ClassTag, not aTypeTag, and use pattern matching.ClassTagswork well with pattern matching. You can even use thecollectmethod to perform thefilterandmaptogether:For example:
One problem with this is that it might not work as expected with nested generic types.
The
collectmethod takes in a parameter of typePartialFunction, representing a function that does not need to be defined on the entire domain. When usingcollectelements where thePartialFunctionis undefined are filtered out, and elements that matched somecasestatement are mapped accordingly.You can also use existential types and let the compiler deduce the type of the
dataparameter for a more concise syntax. You can also use context bounds:One problem with the methods here is that there is a significant difference between the native
filtermethod you have: these methods always returns aTraversablewhile the nativefilterreturns the best type it can. For example:You can fix this by using the
CanBuildFrompattern using another implicit parameter. You can also use implicit classes to essentially add the method to the class (as opposed to calling the method in the static style shown above). This all adds up to a pretty complicated method, but I'll leave it here if you're interested in these enhancements:This would allow you to do: