how can I do a pattern match over a reflect.runtime.universe.Type?
def test(t: reflect.runtime.universe.Type) {
t match {
case Int => \\ ...
case Double => \\ ...
case String => \\ ...
case _ => \\ ...
}
}
This dosn't work, as the interpreter complains:
error: pattern type is incompatible with expected type;
found : Int.type
required: reflect.runtime.universe.Type
Note: if you intended to match against the class, try `case _: Int`
case Int => // ...
^
Trying the suggestion does not work either:
def test(t: reflect.runtime.universe.Type) {
t match {
case _: Int => \\ ...
case _: Double => \\ ...
case _: String => \\ ...
case _ => \\ ...
}
}
...
error: pattern type is incompatible with expected type;
found : Int
required: reflect.runtime.universe.TypeApi
case _: Int => // ...
^
So what is the correct syntax for this?
Thanks!
The TypeTag
API has a comparison operator =:=
and a method for obtaining the Type
instance for a given class, you can combine these with guards to obtain the desired result:
import scala.reflect.runtime.universe._
def test(t: Type) {
t match {
case t if t =:= typeOf[Int] => println("int")
case t if t =:= typeOf[String] => println("string")
case _ =>
}
}
As lmm and n1r3 pointed out, you might be better off to use an if here. However, you could do something like the following:
import reflect.runtime.universe._
case class TypeComparer[A](typeToCompare: TypeTag[A]){
def unapply(universeType: Type) = universeType =:= typeToCompare.tpe
}
object TypeComparer{
val IntComparer = new TypeComparer(typeTag[Int])
}
object TestObject{
def tester(t: Type) {
t match {
case TypeComparer.IntComparer() => println("pass")
case _ => println("fail")
}
}
def test[A](implicit ev: TypeTag[A]) = tester(typeOf[A])
}
which you can run like:
TestObject.test[Int] //pass
TestObject.test[Boolean] //fail
The downside is that you need to create a concrete object for every comparer as I do not know of a way to have companion object with a type used in the apply
So, it is a bit verbose....and the if is probably better here.
Ok, I found a workaround:
def test(t: reflect.runtime.universe.Type) {
t.toString match {
case "Int" => \\ ...
case "scala.Int" => \\ ...
case "Double" => \\ ...
case "scala.Double" => \\ ...
case "String" => \\ ...
case _ => \\ ...
}
}
However, is there a better solution that avoids going via strings?