我在Scala中使用typetags来匹配选项
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")
}
}
所以当我以这种方式使用这个功能时
foo[List[Any]](val)
一切都会好,在这种情况下输出是“列表选项”。 但是当我尝试在没有TypeTag
的情况下使用它时foo(val)
输出为“列表选项”,无论是[Option [Any]]还是Option [String]。
所以现在我的问题: 是否可以为我的TypeTag T定义默认值? 如果不需要TypeTag,我想使用我的函数,然后输出应该是“String”而不是“List Option”。 可以为参数定义默认值,因此可能也适用于TypeTag。
答案 0 :(得分:1)
您的问题是T
类型与参数bar
的类型无关。
这意味着,如果您未明确添加类型,编译器将推断Nothing
,因为它没有进一步的信息。
Nothing
是所有内容的子类型,因此您的子类型检查已经在第一个分支中成功(实际上所有情况都适用于Nothing
)。
您的代码可以像这样“改进”:
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")
}
}
我说“改进”因为永远不应该写这样的代码。感觉它试图将一些成语从无类型语言中剔除到Scala中。
答案 1 :(得分:0)
def foo[T: TypeTag](bar: Any)
只是
def foo[T](bar: Any)(implicit tt: TypeTag[T])
因此,您可以提供默认值:
def foo[T](bar: Any)(implicit tt: TypeTag[T]=...)
答案 2 :(得分:0)
最简单的方法是解决方案。
我写了另一个函数。 现在,如果我需要TypeTags,我可以使用fooType,否则我可以使用foo。
def foo(bar: Any) = {
fooType[String](bar)
}
def fooType[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")
}
}