Let's take this for an example:
import scala.reflect._
def get[T](list: List[Any])(implicit tag: ClassTag[T]) = {
list.flatMap {
case element: T => Some(element)
case _ => None
}
}
I can use get()
to get values of type T
from a list (e.g. get[String](list)
will give me all strings from that list).
Now, I understand that compiler provides the value of type ClassTag[String]
automatically. I also understand that ClassTag
is a type class, and somewhere behind the curtain there's a piece of code that says implicitly[ClassTag[T]].getRuntimeClass()
or whatever.
But if that's so, how come we can pattern match without the class tag (we just can't differentiate between erased types in that case)? I mean, how is it achieved that, if I declare an implicit parameter (which is automatically provided by the compiler), I get one behavior, but if i don't I get a different behavior?
The compiler automatically translates your code roughly to this:
ClassTag
has anunapply(x: Any)
overload that allows it to pattern match on values. I've cleaned up the tree obtained fromreify
to only show the relevant parts, but this will show you the full tree:Also see the scaladoc: