我在某些2.9.2代码中使用man.typeArguments
,但收到了Manifest
s已被弃用的消息。我想出了如何使用typeOf[T]
来访问<:<
方法,但我不能在我的生活中找出typeArguments
去过哪里。
对于上下文,我正在编写createParser[T: TypeTag]
方法。如果T
是List[X]
,那么我会通过链接createParser[X]
列表来创建其解析器。或者那就是我想要做的事。无论如何。
有人知道我应该从X
(或T
或typeOf[T]
或任何其他可能的typeTag[T]
相邻概念中获取T
吗?
这是2.9.2中的代码:
def getParser[T](implicit man: Manifest[T]): Parser[T] = {
if (man <:< manifest[Stream[_]]) {
val itemType = man.typeArguments(0)
streamParser(itemType).asInstanceOf[Parser[T]]
} else {
parsers(man)().asInstanceOf[Parser[T]]
}
}
def streamParser[T](implicit man: Manifest[T]): Parser[Stream[T]] = {
val itemParser = getParser(man)
(openParser("[") ~> repsep(itemParser, comma) <~ closeParser("]")) ^^ (_.toStream)
}
这是我在2.10.1中尝试的内容,但没有太多运气:
def getParser[T](implicit tag: TypeTag[T]): Parser[T] = {
if (tag.tpe <:< typeOf[Stream[_]]) tag.tpe match {
case TypeRef(_, _, List(itemType)) => streamParser(itemType).asInstanceOf[Parser[T]]
} else {
parsers(tag)().asInstanceOf[Parser[T]]
}
}
def streamParser[T](implicit tag: TypeTag[T]): Parser[Stream[T]] = {
val itemParser = getParser(tag)
(openParser("[") ~> repsep(itemParser, comma) <~ closeParser("]")) ^^ (_.toStream)
}
问题在于它说itemType
是来自反射API的Type
,但我无法弄清楚如何将其变成适合发送到{{TypeTag
的{{1}} 1}}。
该streamParser
值实际上是从parsers
到TypeTag
s的地图,将所有内容放入Parser
方法并匹配可能会更清晰我要解析的东西的类型,但到目前为止,我对类型模式匹配的尝试似乎没有用。
我确信有一种简单的方法可以做到这一点 - 我想我只是陷入了一种新的实现和文档之间,而这些实现还没有赶上它。
答案 0 :(得分:1)
在2.10(甚至2.11中更多)中,从类型和树中提取信息的方法是使用模式匹配,在本例中使用TypeRef
:
scala> typeOf[List[Int]] match { case TypeRef(_, _, args) => args }
res13: List[reflect.runtime.universe.Type] = List(Int)
scala> typeOf[Map[Int, String]] match { case TypeRef(_, _, args) => args }
res14: List[reflect.runtime.universe.Type] = List(Int, String)
scala> val TypeRef(_, _, args) = typeOf[List[Int]] // slightly shorter
args: List[reflect.runtime.universe.Type] = List(Int)