Max van Deursen Max van Deursen -4 years ago 120
Scala Question

Scala - Using parametric to specify type in function

Good day,

I have an assignment in university where we needed to write a parser for a certain language. One of the core features of this language was writing an equals method for both NumCs and StringCs (The Number and String representation in the core language). Both of these method would evaluate to BoolV(x), where x is either true or false (BoolV stands for the Boolean Value in this language).

I have succeeded in doing so with the following code (Please note that all inputs are ExprC, which is the superclass of all Core representations of functionality. Moreover, the

interp
functions take care of translating the ExprC into Values):

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.")
}


As you might notice, these functions are very much alike; only the type that is checked changes (As well as the exception, but these are both subclasses from the same exception).

Now I was wondering whether there is some utility that would produce something like the following functionality:

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 + ".")


This would mean that one could specify in one way another the type that the interp of both
l
and
r
has to result in, in order for the compare method to evaluate rather than to throw an error. I know that the above code is by no way correct syntax, but I was wondering whether there is a way to code this functionality within Scala.

Answer Source

Using ClassTag is probably what you are looking for to solve your problem:

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 + ".")
    }
}
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download