Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Generics 与泛型类型的值进行模式匹配_Generics_Scala_Pattern Matching - Fatal编程技术网

Generics 与泛型类型的值进行模式匹配

Generics 与泛型类型的值进行模式匹配,generics,scala,pattern-matching,Generics,Scala,Pattern Matching,我正在编写基于树的表达式计算器,在类型擦除方面遇到了一些问题 这棵树看起来像 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(nam

我正在编写基于树的表达式计算器,在类型擦除方面遇到了一些问题

这棵树看起来像

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
这种情况看起来像是清单的用例,但我无法正确添加它们。

这似乎有效:

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
复杂得多。

这似乎有效:

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
复杂得多。

它不起作用,因为
t
被擦除了。这意味着模式匹配中的
value:T
没有意义。事实上,编译器应该警告您这一点


您将不得不求助于使用清单来进行测试。请参见的示例。

它不起作用,因为
t
被擦除。这意味着模式匹配中的
value:T
没有意义。事实上,编译器应该警告您这一点

您将不得不求助于使用清单来进行测试。请参见的示例