2013-03-24 53 views
0

我在某些2.9.2代碼中使用man.typeArguments,但收到消息Manifest已過時。我想出瞭如何使用typeOf[T]來訪問<:<方法,但我不能在我的生活中找出typeArguments去過的地方。如何獲取typeArguments?

對於上下文,我正在編寫一個createParser[T: TypeTag]方法。如果TList[X]那麼我通過鏈接createParser[X]列表來創建其解析器。無論如何,這就是我想要做的。

任何人都知道我應該怎麼從T(或typeOf[T]typeTag[T]或任何其他可能T -adjacent概念得到X

下面是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) 
    } 

問題是,我t說itemType是來自反射API的Type,但我無法弄清楚如何將它變成適合發送到streamParserTypeTag

parsers值實際上是TypeTag個地圖Parser秒,它很可能是清潔只是把所有的東西都getParser方法和匹配的我想分析事物的類型,但我試圖在模式迄今爲止,類型上的匹配似乎還沒有工作。

我確定有一個簡單的方法可以做到這一點 - 我想我只是在一個新的實現和文檔之間沒有抓住它。

+0

艙單實際上沒有過時,因爲Scala反射仍然是實驗性的。 – ghik 2013-03-24 10:10:23

+0

雖然這是正確的,但它們的使用確實會導致編譯器警告出現。 – TOB 2013-03-24 21:46:36

+0

實際上,它只是導致棄用警告的'<:<'方法,所以我想我會堅持使用它們,直到TypeTag能夠做我需要的。 – TOB 2013-03-25 12:14:18

回答

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) 
+0

這看起來像我正在尋找的東西,然後我嘗試了它,而事實並非如此。我會編輯這個問題,使其更清晰。 – TOB 2013-03-24 21:47:23

+0

@TOB:你想做什麼是不可能的。添加TypeTags是一個編譯時操作,你不能在運行時提取它們,並假定編譯器知道它們。我假設你想要的是你的'parsers'是一個'Map [Type,Parser [_]]'。 – sschaef 2013-03-25 00:09:15

+0

除了它在2.9.2中使用'.typeArguments'和'Manifest'。那麼是不可能的事情呢? – TOB 2013-03-25 00:37:07