美好的一天,
我在大学有一项任务,我们需要为某种语言编写解析器。这种语言的核心功能之一是为NumC和StringC编写一个equals方法(核心语言中的数字和字符串表示)。这两种方法都将评估为BoolV(x),其中x为true或false(BoolV代表该语言中的布尔值)。
我使用以下代码成功完成了这项操作(请注意,所有输入都是ExprC,它是所有Core功能表示的超类。此外,public static IImmutableList<SupportRequest> GetSupportRequestsByClientId(this IDbSet<SupportRequest> dbSet, Guid clientId)
{
// Do stuff here
return ...;
}
函数负责将ExprC转换为值):
interp
您可能会注意到,这些功能非常相似;只检查的类型发生了变化(以及异常,但这些都是来自同一异常的子类)。
现在我想知道是否有一些实用程序会产生类似以下功能:
def str_cmp(l: ExprC, r: ExprC): BoolV = (interp(l), interp(r)) match {
case (StringV(x), StringV(y)) => BoolV(x == y)
case _ => throw NotStringException("Atleast one argument value does not evaluate to a String.")
}
def num_cmp(l: ExprC, r: ExprC): BoolV = (interp(l), interp(r)) match {
case (NumV(x), NumV(y)) => BoolV(x == y)
case _ => throw NotNumberException("Atleast one argument value does not evaluate to a number.")
}
这意味着可以以一种方式指定另一种def compare[A](l: ExprC, r: ExprC): BoolV = (interp(l), interp(r)) match {
case (A(x), A(y)) => BoolV(x == y)
case _ => throw NotValidArgument("Atleast one argument value does not evaluate to " + A + ".")
和l
的interp必须导致的类型,以便比较方法进行评估而不是抛出错误。我知道上面的代码绝不是正确的语法,但我想知道是否有办法在Scala中编写这个功能。
答案 0 :(得分:1)
使用ClassTag可能就是您正在寻找的解决问题的方法:
import reflect.ClassTag
def compare[T : ClassTag](l: ExprC, r: ExprC): BoolV = {
val ct = implicitly[ClassTag[T]]
(interp(l), interp(r)) match {
case (ct(x), ct(y)) => BoolV(x == y)
case _ => throw new Exception("At least one argument value does not evaluate to " + ct + ".")
}
}