【问题标题】:Pattern matching against value with generic type与泛型类型的值进行模式匹配
【发布时间】:2011-10-25 17:10:24
【问题描述】:

我正在编写基于树的表达式求值器,但在类型擦除方面遇到了一些麻烦。

树看起来像

sealed abstract class Node[+T]
case class Var[+T](name:String) extends Node[T]
/* SNIP */

评估者是

def eval[T](node:Node[T], context:Map[String, Any]):Option[T] = node match {
  case Var(name) => context.get(name) match {
    case Some(value:T) => Some(value)
    case _ => None
  }
  /* SNIP */
}

代码可以编译,但对Var 节点的类型检查不起作用。所以这个测试失败了:

class ContextEvaluatorTest extends FunSuite with ShouldMatchers {
  test("evaluation with type mismatch") {
    ContextEvaluator.eval(Var[Int]("a"), Map("a" -> "not int")) should equal (None)
  }
}

错误信息是

org.scalatest.TestFailedException: Some(not int) did not equal None

情况看起来像是清单的用例,但我无法正确添加它们。

【问题讨论】:

    标签: generics scala pattern-matching


    【解决方案1】:

    这似乎有效:

    def eval[T:ClassManifest](node:Node[T], context:Map[String, Any]):Option[T] = node match {
      case Var(name) => context.get(name) match {
        case Some(value:T) if classManifest[T].erasure.isInstance(value) => Some(value)
        case _ => None
      }
      case _ => None
    }
    

    但请注意,T 必须是简单类型,AFAIK ClassManifest 无法区分 List[Int]List[String] 之类的东西。可能Manifest可以做到这一点,但是调查比在底层类上调用isInstance更复杂。

    【讨论】:

      【解决方案2】:

      它不起作用,因为T删除。这意味着模式匹配中的value: T 是没有意义的。事实上,编译器应该已经警告过你了。

      您将不得不求助于使用清单来进行该测试。有关示例,请参见 Landeianswer

      【讨论】:

        猜你喜欢
        • 2016-10-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-04-10
        • 1970-01-01
        • 1970-01-01
        • 2018-06-20
        相关资源
        最近更新 更多