2

I have written a generic function to get a value from a HashMap[String, AnyVal]. This method returns a value from the name but also has a functionality to make sure it is of a specific type:

class Context {
  private var variables = HashMap[String, Any] ()

  def getVariable (name: String):Any = variables(name)
  def setVariable (name: String, value: Any) = variables += ((name, value))

  def getVariableOfType[T <: AnyVal] (name:String):T ={
    val v = variables(name)
    v match {
      case T => v.asInstanceOf[T]
      case _ => null.asInstanceOf[T]
    }
  }

}

The function getVariableOfType[T <: AnyVal] will not compile because it says "Cannot resolve symbol T" at the line case T => v.asInstanceOf[T]

5
  • To make it compile, you probably meant: case something: T => v.asInstanceOf[T] /*or better just: something */. Though it is not recommended, you should use TypeTags. Commented Aug 17, 2015 at 9:01
  • @GáborBakos I am trying to match by type but I will try that thanks Commented Aug 17, 2015 at 9:03
  • 1
    In that case you definitely should use type tags. Otherwise -because of erasure- it will always go on the first case. Commented Aug 17, 2015 at 9:08
  • 1
    Besides what @Gábor says which is why your solution doesn't work, the compiler error is because you're match is wrong. It should be: v match { case _ : T => v.asInstanceOf[T]}, otherwise the compiler tries to match v to an already defined value called T. Commented Aug 17, 2015 at 9:20
  • This explains type tags even better than the official documentation. Commented Aug 17, 2015 at 9:41

1 Answer 1

6

Simply having case x: T => v.asInstanceOf[T] will match any type because of erasure. To really do the type checking you have to make a ClassTag available for T: [T <: AnyVal : ClassTag].

Here is a working definition of getVariableOfType:

import scala.reflect.ClassTag

def getVariableOfType[T <: AnyVal : ClassTag] (name:String):T ={
  val v = variables(name)
  v match {
    case x: T => x
    case _ => null.asInstanceOf[T]
  }
}

The downside is that ClassTag doesn't completely remove the issue of erasure. So requesting for example a Seq[Int], will actually match on every type of sequence (Seq[Double], Seq[String], etc.). In your example T is a subtype of AnyVal, so this won't be an issue.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.