【问题标题】:Scala: pattern matching over a reflect.runtime.universe.Type?Scala:在 reflect.runtime.universe.Type 上进行模式匹配?
【发布时间】:2015-04-02 19:38:42
【问题描述】:

如何对 reflect.runtime.universe.Type 进行模式匹配?

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.type
 required: reflect.runtime.universe.Type
Note: if you intended to match against the class, try `case _: Int`
         case Int => // ...
              ^

尝试该建议也不起作用:

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 => // ...
                 ^

那么正确的语法是什么?

谢谢!

【问题讨论】:

  • ps.: 使用 if 语句,我可以执行以下操作: if (t==reflect.runtime.universe.typeOf[String]) // ... 但是,这不是在模式匹配语法中工作: t match { case reflect.runtime.universe.typeOf[String] => \\ ... case _ => } 我得到提示错误:类型 typeOf 不是 scala.reflect 的成员。 api.JavaUniverse case reflect.runtime.universe.typeOf[String] => fieldMap(pName).set(pVal)
  • 还有一个问题:做if语句我发现scala.Int显然和Int不一样。但是,reflect.runtime.universe.typeOf[scala.Int]) 的结果是 Int,(t==reflect.runtime.universe.typeOf[Int]) 的结果和 if ( t==reflect.runtime.universe.typeOf[scala.Int])。如何解决?
  • 如果不使用if,你需要一个稳定的模式匹配标识符,并且你想使用=:=而不是==。试试case t if t =:= typeOf[String] => ...
  • 模式匹配不是一个好主意:groups.google.com/d/msg/scala-internals/P2_okWT4muw/…。所以,按照@lmm 的建议,使用if 语句和=:=

标签: scala types pattern-matching


【解决方案1】:

TypeTag API 有一个比较运算符=:= 和一个获取给定类的Type 实例的方法,您可以将它们与守卫结合以获得所需的结果:

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】:

    正如 lmm 和 n1r3 指出的那样,你最好在这里使用 if 。但是,您可以执行以下操作:

    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])
    }
    

    你可以像这样运行:

    TestObject.test[Int] //pass
    TestObject.test[Boolean] //fail
    

    缺点是您需要为每个比较器创建一个具体对象,因为我不知道有一种方法可以让伴生对象具有 apply 中使用的类型

    所以,它有点冗长……而且这里的 if 可能更好。

    【讨论】:

      【解决方案3】:

      好的,我找到了解决方法:

      def test(t: reflect.runtime.universe.Type) {
        t.toString match {
          case "Int" => \\ ...
          case "scala.Int" => \\ ...
          case "Double" => \\ ...
          case "scala.Double" => \\ ...
          case "String" => \\ ... 
          case _ =>  \\ ...
        }
      }   
      

      但是,有没有更好的解决方案可以避免通过字符串?

      【讨论】:

        猜你喜欢
        • 2021-04-08
        • 1970-01-01
        • 2022-01-05
        • 2012-12-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-11-12
        相关资源
        最近更新 更多