I'm using typetags in Scala to match options
def foo[T: TypeTag](bar: Any) = {
bar match {
case option: Option[T] => option match {
case x if typeOf[T] <:< typeOf[List[Any]] => println("List Option")
case x if typeOf[T] <:< typeOf[Map[Any, Any]] => println("Map Option")
case x if typeOf[T] <:< typeOf[Boolean] => println("Boolean Option")
case _ => println("String")
}
case _ => println("no Option")
}
}
So when I use the function this way
foo[List[Any]](val)
all will be fine and the output is "List Option" in this case. But when I try to use it without the TypeTag
foo(val)
the outputs is "List Option", regardless of whether it's a Option[List[Any]] or Option[String].
So now my question: Is it possible to define a default value for my TypeTag T? I want to use my function without the TypeTag if it is not needed and then the output should be "String" and not "List Option". It is possible to define a default value for parameters, so maybe it is for TypeTag too.
Your problem is that the type T
is not related to the type of the parameter bar
.
This means, if you don't add the the type explicitly, the compiler will infer Nothing
because it has no further information.
Nothing
is a subtype of everything, so your subtype checks succeeds in the first branch already (in fact all your cases are true for Nothing
).
Your code could be "improved" like this:
import scala.reflect.runtime.universe._
def foo[T: TypeTag](bar: Any) = {
bar match {
case option: Option[T] => option match {
case x if typeOf[T] =:= typeOf[Nothing] => println("Nothing")
case x if typeOf[T] <:< typeOf[List[Any]] => println("List Option")
case x if typeOf[T] <:< typeOf[Map[Any, Any]] => println("Map Option")
case x if typeOf[T] <:< typeOf[Boolean] => println("Boolean Option")
case _ => println("String")
}
case _ => println("no Option")
}
}
I say "improved" because one should never ever write code like this. It feels like it tries to shoehorn some idiom from untyped languages into Scala.