Note this is intended to be a community post, and examples should be added as needed. If you can't directly edit the answer to add examples (either problem examples or solutions), post in a comment with a link to a gist (or similar) or add a separate answer, to be integrated later.
There is the possibility that Scala 3 may not include scala.reflect.runtime
at all (Dotty currently doesn't, and plans to do so are not certain). While answers that are applicable to both Scala 2 and Dotty might be preferred for transition purposes and for immediate improvements in performance, Dotty-specific solutions are also welcome.
https://www.cakesolutions.net/teamblogs/ways-to-pattern-match-generic-types-in-scala
TypeTag
s are generated at compile time (which may have significant compile time overhead due to macro expansion at each use-site) and employed at runtime, also generating some potential runtime overhead, depending on the exact nature of their use. So even in Scala 2, they should probably only be used a last resort (and we hope to address all such issues here, so that a last resort isn't necessary). By comparison, things that use instanceOf
, directly or indirectly, are extremely fast.
instanceOf
is super fast. classOf
(i.e. Java's getClass
) is nearly as fast.
Referential equality on ClassTag
s should also be very fast.
When possible, you may want to consider wrapping your type in a class, to give it a concrete "Java" type. While there will often be overhead, you can possibly use value classes.
Type classes on the wrapped class are then often a good way to expose functionality. As an aside, as @Blaisorblade pointed out, " type tags just a lawless type class (with methods typeName: String
and tpe: Type
) + instance materialization". Which brings us to the next option:
(currently not supported in Dotty, but planned)
Although perhaps a little harder to get used to, the end result should be cleaner syntax in the code employing the macro than if you were using a TypeTag
. Also, macros have uses far beyond TypeTag
.
A typical use case for TypeTag
, taken from the popular post Scala: What is a TypeTag and how do I use it? is to perform ad-hoc polymorphism on a collection type:
import scala.reflect.runtime.universe._
def meth[A : TypeTag](xs: List[A]) = typeOf[A] match {
case t if t =:= typeOf[String] => "list of strings"
case t if t <:< typeOf[Foo] => "list of foos"
}
scala> meth(List("string"))
res67: String = list of strings
scala> meth(List(new Bar))
res68: String = list of foos
Unlike ClassTag
, TypeTag
is runtime reflection. Maybe I'm using it wrong here, though the behavior is quite surprising. At least in a REPL, I don't receive any warnings with the below:
def meth[A : ClassTag](xs: List[A]) = xs match {
case xs: List[String] => "list of strings"
case xs: List[Foo] => "list of foos"
}
meth(List(new Bar))
res10: String = "list of strings"
This is from @smarter on gitter (assumes we don't need to handle empty lists of different types separately):
def meth[A](xs: List[A]) = xs match {
case Nil => "nil"
case (_: String) :: _ => "list of strings"
case (_: Foo) :: _ => 'list of foos"
}
This uses instanceOf
, so it should be extremely fast.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With