I’m digging new scala reflection api and can’t figure out why the following snippet doesn’t work as expected. Given hierarchy (tried to simplify as much as I can):
import scala.reflect.runtime.universe._
trait TF[A] {
implicit def t: TypeTag[A]
def f[T <: A: TypeTag]: PartialFunction[Any, A] = {
case msg: T if typeOf[T] =:= typeOf[A] => msg
}
}
class TFilter[T: TypeTag] extends TF[T] {
def t = typeTag[T]
}
case class Foo(x: Int)
I expect method f to filter objects of given type. So the following snippet should return Seq[Foo]
val messages = Seq(1, "hello", Foo(1))
val tFilter = new TFilter[Foo]
messages collect tFilter.f[Foo]
And it actually returns Seq[Foo] but with other messages unfiltered, which sounds like a bug.
res1: Seq[Foo] = List(1, hello, Foo(1))
Question. Am I using TypeTag wrong or it is defect of new reflection api?
PS0. Tried with Scala 2.10.0-RC1 and 2.10.0-RC2
PS1. The workaround is to replace TypeTag with Manifest, so with the following code collect on sequence will return List(Foo(1)) as expected.
trait MF[A] {
implicit def m: Manifest[A]
def f[T <: A: Manifest]: PartialFunction[Any, A] = {
case msg: T if typeOf[T] =:= typeOf[A] => msg
}
}
class MFilter[T: Manifest] extends MF[T] {
def m = manifest[T]
}
Update: Same with new Scala 2.10.0-RC2 release.
So I think the key problem here is that you need to match against the type of
msg, but its compile-time type isAny(from thePartialFunctiondeclaration). Essentially, you want a differentTypeTagfor each element in yourList[Any]. But since they all have compile-time type ofAnyby virtue of all being put into the same list, you’re not going to get aTypeTagthat’s any more specific than that.I think what you probably want to do is use
ClassTaginstead ofTypeTag:As Ajran points out, just like the
Manifestversion, you’ll have to be aware of all the limitations of runtime types including erasure and boxing issues:There are some suggestions about how to make
TypeTagmore useful for pattern matching (e.g. SI-6517), but I think those will only help when you’re matching against an object with an usefulTypeTag, not an object with compile-time type ofAny.