reflection - 通過Scala 2.10中的反射查找類型參數?





scala-2.10 (3)


Scala 2.11開始,您可以簡單地使用:

yourGenericType.typeArgs.head

請參閱宏更改日誌點編號14。

使用類型標籤,我能夠看到某些類型的參數:

scala> import scala.reflect.runtime.universe._
import scala.reflect.runtime.universe._

scala> typeOf[List[Int]]
res0: reflect.runtime.universe.Type = List[Int]

但我只是不知道如何以一般方式以編程方式從那裡獲得“Int”。

(我已經在REPL中閒逛了一個小時,在Type上嘗試排列,看看我能從中得到什麼......我得到了很多東西,表明這是一個“列表”,但是找到了好運那個“Int”!我真的不想解析toString()輸出......)

丹尼爾·索布拉爾(Daniel Sobral) here有一個非常好的(通常)快速概述,其中他非常接近我正在尋找的東西,但(顯然)只有你碰巧知道,對於那個特定的類,一些特定的方法,其類型可以是詢問:

scala> res0.member(newTermName("head"))
res1: reflect.runtime.universe.Symbol = method head

scala> res1.typeSignatureIn(res0)
res2: reflect.runtime.universe.Type = => Int

但是我希望有一些更通用的東西,它不涉及在聲明的方法列表中生根,並希望其中一個將捕獲(並因此洩露)標籤的當前類型信息。

如果Scala可以如此輕鬆地打印 “List [Int]”,那麼為什麼發現“Int”部分很難 - 不使用字符串模式匹配? 或者我只是遺漏了一些非常非常明顯的東西?

scala> res0.typeSymbol.asInstanceOf[ClassSymbol].typeParams
res12: List[reflect.runtime.universe.Symbol] = List(type A)

scala> res12.head.typeSignatureIn(res0)
res13: reflect.runtime.universe.Type = 

格兒...




遺憾的是,我不認為有一種方法可以為您提供參數,但您可以通過這種方式獲取它們:

Welcome to Scala version 2.10.0-20121007-145615-65a321c63e (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_35).
Type in expressions to have them evaluated.
Type :help for more information.

scala> import scala.reflect.runtime.universe._
import scala.reflect.runtime.universe._

scala> typeOf[List[Int]]
res0: reflect.runtime.universe.Type = scala.List[Int]

scala> res0 match { case TypeRef(_, _, args) => args }
res1: List[reflect.runtime.universe.Type] = List(Int)

scala> res1.head
res2: reflect.runtime.universe.Type = Int

編輯這裡是一個更好的方法來實現相同的事情(在討論scala-internals之後 ):

scala> res0.asInstanceOf[TypeRefApi].args
res1: List[reflect.runtime.universe.Type] = List(Int)



如果不重複,我不相信這是可能的。 有一個簡單的原因:你不能定義你要求的函數的返回類型。

例如,如果你的輸入是List(List(1,2),List(3,4)),那麼返回類型是List [Tuple2 [Int]]。 如果它有三個元素,返回類型將是List [Tuple3 [Int]],依此類推。

你可以返回List [AnyRef],甚至可以返回List [Product],然後創建一組情況,每個情況一個。

至於一般的List轉置,這個工作:

def transpose[T](l: List[List[T]]): List[List[T]] = l match {
  case Nil => Nil
  case Nil :: _ => Nil
  case _ => (l map (_.head)) :: transpose(l map (_.tail))
}




scala reflection scala-2.10