我如何获得类型参数? [英] How do I get typeArguments?

查看:31
本文介绍了我如何获得类型参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在某些 2.9.2 代码中使用了 man.typeArguments,但收到一条消息,指出 Manifest 已被弃用.我想出了如何使用 typeOf[T] 来访问 <:< 方法,但我终生无法弄清楚 在哪里typeArguments 已经去了.

I was using man.typeArguments in some 2.9.2 code, but got a message that Manifests are deprecated. I figured out how to use typeOf[T] to access the <:< method, but I can't for the life of me figure out where typeArguments has gone to.

对于上下文,我正在编写一个 createParser[T: TypeTag] 方法.如果 T 是一个 List[X],那么我通过链接一个 createParser[X] 列表来创建它的解析器.或者,无论如何,这就是我想做的.

For context, I'm writing a createParser[T: TypeTag] method. If T is a List[X] then I create its parser by chaining a list of createParser[X]. Or that's what I'd like to do, anyway.

任何人都知道我应该如何从 T(或 typeOf[T]typeTag[T]> 或任何其他可以想象的 T-相邻概念?

Anybody know how I should get X from T (or typeOf[T] or typeTag[T] or any other conceivable T-adjacent concept?

这是 2.9.2 中的代码:

Here's the code in 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 中尝试的,但运气不佳:

Here's what I'm trying in 2.10.1, but not having much luck with:

  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 适用于发送到 streamParser.

The problem is that it says itemType is a Type from the reflection API, but I can't figure out how to turn that into a TypeTag suitable for sending to streamParser.

那个 parsers 值实际上是一个从 TypeTags 到 Parsers 的映射,把所有东西都放到getParser 方法并匹配我想要解析的事物的类型,但我对类型进行模式匹配的尝试到目前为止似乎还没有奏效.

That parsers value is actually a map from TypeTags to Parsers, and it would probably be cleaner to just put everything into the getParser method and match on the type of the thing I want to parse, but my attempts at pattern matching on types haven't seemed to work so far.

我确信有一种简单的方法可以做到这一点——我想我只是被新的实现和尚未赶上它的文档夹住了.

I'm sure there's an easy way to do this--I think I'm just caught between a new implementation and documentation that hasn't caught up to it.

推荐答案

在 2.10 中(甚至在 2.11 中更多)从类型和树中提取信息的方法是使用模式匹配,在这种情况下使用 TypeRef:

In 2.10 (and even more in 2.11) the way to extract information out of types and trees is to use pattern matching, in this case with 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)

这篇关于我如何获得类型参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆