Scala: pattern matching over a reflect.runtime.universe.Type?

六眼飞鱼酱① 提交于 2019-12-20 02:59:04

问题


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!


回答1:


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 _ =>  
  }
} 



回答2:


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.




回答3:


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?



来源:https://stackoverflow.com/questions/28301787/scala-pattern-matching-over-a-reflect-runtime-universe-type

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!